C语言_函数栈帧的创建与销毁

简单了解

想要了解函数栈帧得先知道两个寄存器(ebp,esp),这两个寄存器存放的是地址,这两个地址是用来维护函数栈帧的。每一个函数调用都要在栈区创建一个空间。

这是根据右侧代码画了一个简略的图

其实,main也是被其他函数调用的。


深度剖析 

接下来我们根据之前的右侧代码转成汇编深度剖析它的行为。 

这是调用main之前的样子。

我们来看一下代码转成反汇编的样子。


main栈帧的开辟

push        ebp  :将ebp的值压栈。 

mov        ebp,esp :将esp的值给ebp。

sub        esp,0E4h :esp 减 0E4h。意味着esp往上走了。

push        ebx                                                                                                                              push        esi                                                                                                                                      push        edi :压栈

lea(load effective address) 加载有效地址。

把[ebp-0E4h]加载到edi, 把39h放在ecx, 把0CCCCCCCCh放在eax。

 dword(double word), 一个word两字节,dword四字节。

从edi向下每次初始化dword(四字节),初始化ecx(39h)次,初始化内容为eax(0CCCCCCCCh)。


main局部变量创建

把0Ah放到[ebp-8], 把14h放到[ebp-14h], 把0放到[ebp-20h]。

函数局部变量创建的基本思路:先创建函数栈帧,在栈帧里面找一些空间存放。


给Add传参

把ebp-14h的值赋给eax然后再把eax的值压栈,同理把ebp-8的值赋给ecx然后再把ecx值压栈。


调用Add

接下来是call指令,执行call同时会把call的下一条指令的地址压入栈。


进入Add       

这里开辟Add的函数栈帧,和之前开辟的思想是一样的。

把[ebp+FFFFFF34h]加载到edi, 把33h放到ecx, 把0CCCCCCCCh放到eax。从edi这个位置开始向下到ebp所有内容初始化成CCCCCCCC。

计算任务

先在ebp-8位置初始化为0,这是创建临时变量z, 然后找到之前传入的参数相加放入eax再给z, 返回时z把值给eax,函数返回z会销毁,所以要存入寄存器中。


返回 销毁Add

pop: 将栈顶元素弹出放到指定位置。

把edi, esi, ebx弹出,再把ebp赋值给esp。

然后pop ebp,  pop ebp的意思:把栈顶上那个元素弹出,放进ebp里。此时栈顶的元素存放着main时期对应的ebp值,所以此时ebp又回到了main时期ebp的位置。   

       

此时栈顶元素是回去的地址,ret负责弹出栈顶元素并跳转到该地址。 

 

接下来是形参的销毁。esp+8是往下走两个。

再将eax值给c。

  • 34
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值