函数栈帧的创建与销毁(分步超详细讲解)

问题

在学完此文章之后我将会对以下问题作出解答
1.局部变量怎么创建的
2.为什么局部变量不初始化,它的值是随机值(全局变量不初始化默认为0)
3.函数是怎么传参的,传参的顺序是怎么样的
4.形参和实参的关系
5.函数的调用是怎么做到的
6.函数的调用结束后是怎么返回的

正式环节

首先我们创建如下代码

Add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}
int main()
{
	int a = 10;
	int b = 20;
	int c = 0;
	c = Add(a, b);
	printf("%d", c);
	return 0;
}

我们要注意main函数也是被其他函数调用的
1.创建好代码后我们按f10调试,右击鼠标点击转到反汇编即可(为了便于观察我们右击鼠标将显示显示符号名去掉)
2.我们今天会遇见诸如eax,ebx,ecx,edx,ebp,esp的寄存器,其中ebp,esp这两个寄存器存放的是地址,用来维护函数的栈帧
3.每次函数的调用都会在栈区开辟一块空间(内存中包含栈区,堆区,静态区),栈区底部为高地址,顶部为低地址
我们将ebp称为栈低指针,esp称为栈顶指针
4.当我们进入main函数时,esp,ebp还在维护调用main函数的函数的栈帧,我们需要将ebp,esp维护main函数的栈帧

汇编指令

mov:数据转移指令
push:数据入栈,esp栈顶寄存器会发生改变
pop:数据弹出至指定位置,esp栈顶寄存器会发生改变
call:函数调用
jump:通过修改eip,转入目标函数,进行调用
ret:恢复返回地址,压入eip
sub:减法命令
add:加法命令
lea:load effective adress(加载有效地址)

维护main函数的栈帧

1.push ebp 意为压栈,将ebp压在栈区中,由于esp的始终指向栈顶,那么esp的地址会减小,我们可以在窗口打开内存输入esp的地址,可以观察到ebp确实被压进去了
2.move指令将esp的值赋给ebp,使其上移,sub指令将esp减去一个值,使其esp上移,此时开辟的空间就是维护main函数的函数的栈帧

初始化

1.将ebx,esi,edi压栈
2.lead,move,move,rep stos这一系列操作将此地址载入edi,从edi开始,向下39h次数的dword数据全改为0cccccccch

在这里插入图片描述
3.将a,b,c的值放入函数的栈帧里去

在这里插入图片描述

调用Add()

4.接下来是把b,a的值分别放在eax,ecx里去同时将eax,ecx压栈

在这里插入图片描述
5.接着我们执行call指令,在执行call指令是我们又在栈区放入了call指令的地址的下一条地址,为了方便在调用完Add函数后能接着从此地址向下运行

在这里插入图片描述
6.进入Add函数后前面的执行与main类似,走到后边我们发现把ebp+8的值给eax,实际就是把a的值放入eax中
之后加上b的值,一起放入z中

在这里插入图片描述
7.我们把计算出来的ebp-8的值放入eax中,eax是寄存器,所以出Add函数,这个值不会销毁
在这里插入图片描述

返回main()

8.用pop将栈顶的寄存器弹出,接着让把ebp的值赋给esp,接着popmain函数的ebp,即将main函数的ebp赋给ebp使其回到main函数底部,因为下一条地址存着call指令地址的下一条地址,最后ret指令让call指令的下一条指令弹出,然后跳到那去,使其回到call指令的下一条地址

在这里插入图片描述
9.最后将eax即z的值放入ebp-20即c中

在这里插入图片描述
在这里插入图片描述

问题解答

1.首先为函数分配栈帧空间,初始化这部分空间,之后给局部变量从这部分空间中分配空间
2.我们在初始化函数栈帧空间时放的是随机值,局部变量不初始化,那它的值就是这个随机值
3.当我们还没有调用函数时候,我们已经把参数从右向左通过压栈压进来,在调用函数时我们通过指针偏移量来找到形参
4.形参是在压栈时分配的一块空间,它与实参的空间是相互独立的,只是数值相同,所以形参是实参的一份临时拷贝
5.通过call指令来实现函数调用,但在栈区会留下call指令的地址的下一条指令的地址放入栈区,以便后面能返回来继续执行
6.在我们调用函数之前就把原来函数的ebp压进栈里,回来是直接pop ebp就能让ebp回到原来函数的ebp,esp向下走就可以找到原来函数的ebp,我们又把call指令的下一条指令地址压进栈中,就可以通过这个地址让我们的函数返回,返回值是通过寄存器的方式带回

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值