【C语言深剖】函数栈帧的创建与销毁

楔子

  • 什么是栈

栈作为一种数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)

  • 什么是栈帧

从逻辑上讲,栈帧就是一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里等等。栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息

  • 寄存器

首先寄存器的功能是存储二进制代码,我们现在先认识这几个寄存器:

寄存器功能
eax通用寄存器,保留临时数据,常用于返回值
ebx通用寄存器,保留临时数据
ebp栈底寄存器
esp栈顶寄存器
eip指令寄存器,保存当前指令的下一条指令的地址
  • 一些汇编语言
名称作用
mov数据转移指令
push数据入栈,同时esp栈顶寄存器也要发生改变
pop数据弹出至指定位置,同时esp栈顶寄存器也要发生改变
sub减法命令
add加法命令
call函数调用,1. 压入返回地址 2. 转入目标函数
jump通过修改eip,转入目标函数,进行调用
ret恢复返回地址,压入eip,类似pop eip命令

调用main函数

  • 代码如下:
int MyAdd(int a, int b)
{
	int c = 0;
	c = a + b;

	return c;
}

int main()
{
	int x = 0xA;
	int y = 0xB;
	int z = 0;

	z = MyAdd(x, y);

	printf("%d\n", z);
	return 0;
}
  • 今天我们要了解这张图的栈区:
  • 在这里插入图片描述

在这里插入图片描述

  • 现在我们大体的框架已经构建好了,接下来就是main函数栈帧的形成

在这里插入图片描述

  • 绿色部分
    将ebp压栈->把esp中的值赋给ebp,此时ebp指向main函数的栈底->esp的值减去0E4h(由于esp的地址高,所以是在ebp上方开辟了大小为0E4h的空间),此时main函数的栈帧形成(由esp和ebp共同维护)

  • 蓝色部分
    ebx,esi,edi按次序入栈

  • 紫色部分
    注:区分一下mov和lea
    lea eax,[ebx+8]就是将ebx+8这个值直接赋给eax,而不是把ebx+8处的内存地址里的数据赋给eax。而mov指令则恰恰相反,例如:mov eax,[ebx+8]则是把内存地址为ebx+8处的数据赋给eax。
    把[ebp-24h]的值直接赋给edi->把9存到ecx中->把0CCCCCCCCCh存到eax中->rep stos作用是重复拷贝,dword 双字 ,就是四个字节ptr , pointer缩写 即指针,[]里的数据是一个地址值,这个地址指向一个双字型数据,连起来就把mian栈帧里面的内容全部初始化为0CCCCCCCh->把内存地址为5CC00Fh的数据赋给ecx->调用005C1320的函数

形成临时变量

在这里插入图片描述

  • 粉色部分
    分别把x,y,z的值放入[ebp-8],[ebp-14h],[ebp-20h]中

  • 灰色部分
    把[ebp-14h]的值放入eax,然后压栈,后面同理,
    这里我们可以得到一个结论:函数形参是在函数调用前形成的,先y后x,由此可见,形参实例化时从左向右的。

注:
由于x和y是相差4个字节,我们可以直接通过指针访问b来修改b的值
在这里插入图片描述

调用函数

在这里插入图片描述

call命令的作用
将当前指令的下一条指令入栈(push到栈中,影响esp)
跳转到目标函数地址运行(修改eip,到达目标函数)

形成Add函数栈帧

在这里插入图片描述

  • 红色部分
    直接把ebp的值压栈->把esp的值赋给ebp->esp减去0CCh->此时esp和ebp共同维护add的栈帧

  • 蓝色部分
    把Add函数栈帧初始化

  • 绿色部分
    [ebp + 8]和[ebp + 0Ch]分别是形参a,b;然后直接通过寄存器把[ebp-8]的值(也就是c的值)修改为21;然后把c的值放入eax寄存器中

释放add栈帧

在这里插入图片描述
将edi,esi,ebx,pop也就是删除->esp的值加上0CCh此时esp和ebp指向同一位置(释放”栈帧“)->把ebp删除(ebp向下访问4个字节,就是main函数的栈底,此时ebp又恢复原来的指向)->esp指向内容为add地址处->ret就是把eip中的值修改为add的地址,然后返回到add处

释放main栈帧

在这里插入图片描述
esp加8就是让esp向高地址指向,就是把形参释放->然后把eax的值放到[ebp - 20h]也就是z,这样就完成带回返回值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zzt.opkk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值