函数栈帧的创建和销毁

函数栈帧的创建和销毁

在不同的编译环境下,函数调用过程中栈帧的创建是略有差异的,但是逻辑是相同的。

寄存器:

  1. eax
  2. ebx
  3. ecx
  4. edx

  1. ebp
  2. esp

ebp,esp这两个寄存器中存放的是地址,这两个地址是用来维护函数栈帧的。

每一个函数调用,都要在栈区创建一个空间

假设我们建立了main函数这块空间就由esp和ebp共同维护了,正在调用哪个函数,esp和ebp就维护哪个函数,例如这里我们调用了add函数,这里我们的esp和ebp就共同维护了这块空间,通常把ebp叫栈低指针,esp叫栈顶指针。栈区的使用习惯,从高地址到低地址,按f10,之后点击鼠标右键进入反汇编,这就是我们所写代码的反汇编

在main函数执行前,有这个函数先执行

Push ebp,压栈(给栈顶里面放个元素进去)

出栈(从栈顶删除一个元素)pop

可以发现esp的地址变小了,因为压栈了(压了一个ebp进去)地址是由高到低,之前加个ebp所以esp变小了。

之后的move是把esp的值赋给ebp,这时ebp就变化了指向了压进去的ebp

Sub是减oE4h是一个八进制数字,算出来为228,main函数调用前会调用_tmainCRTStartup函数,当esp减少228之后esp跟之前的ebp就组成了新的空间这里就是为main函数开辟的

之后三个push连续压了三个元素进去

esp的位置再次发生变化。

下一步到了lea(load effective address加载有效地址,相当于把后面有效的地址加到edi中)也就是给edi中放了一个地址

rep stos:要把从edi开始向下ecx次dword(double word是四个字节,一个word是两个字节)这么多的空间全部改成0CCCCCCCCh。

这个动作叫我们内存的内一部分全部变成0CCCCCCCCh,

把0Ah(10)放入ebp-8中,如果a没有放入10,那么这里本来就是cccccccch,那么就很好解释我们之前打印随机值内些烫烫烫烫之类的乱码,就是因为内存中有cccccccch。不同的编译器这里放的是不同值,所以就很好解释了为什么一定要赋初值。

这里就能看出00 00 00 0a

这里三个局部变量就建立完毕了。

由此我们梳理一下逻辑,

前面是mian函数创立栈帧

这是三个临时变量的创建。

下面是add函数

把ebp-14(也就是b)放入eax中,这时eax就相当于20,

之后压栈eax(b-20)

把ebp-14(也就是a)放入ecx中,这时ecx就相当于20,

之后压栈ecx(a-10)

上面这两步就是在传参数

在call(这里是指调用函数)按f11,

之后再按一次f11,就真正进入到函数中了

前面这一堆我们发现跟之前mian函数一样,这其实就是为我们的add函数准备栈帧。

Push ebp将之前main函数的ebp压到add下一个语句上面。这时ebp指向esp

之后esp-0CCh

这时就是为了add函数开辟栈帧,之后同main函数一样压栈了ebx,esi,edi,之后同main函数一样放入0ccccccccccch

这里进行了计算

我们发现形参的来源,是我们需要形参它去找之前创建好的而非主动创建的,找到进行push压栈,先传的b再传a,从右往左传。当真的来到函数内部去调用这个函数的时候,形参不是我们从add函数内创建的,而是回去找之前的压栈过来,这就是我们的x,y。这里就深刻体现出形参是实参是临时拷贝。值是一样的,空间不同而已。

之后return z它对应的汇编代码是把ebp-8放入eax中,eax是个寄存器是不会随着程序退出而销毁的。等回到主函数再把eax的值拿出来用就可以.

之后就该销毁了,连续的三个pop将之前压栈的edi,esi,ebx分别出栈。调试从内存中我们也能看出来内存增加4+4+4。

之后mov把ebp指向esp当pop把ebp销毁了,esp就指向这里,这时候就只剩main函数创立的栈了。现在的栈顶是call指令的下一条指令的地址,恰好就esp就找到了这里。这时我们发现当时栈顶创建call指令的下一条指令的地址就是为了ebp销毁之后,esp能找到这里。

之后esp+8就将之前的xy申请的栈销毁了

这是把返回值放入c中。同时main函数的销毁也跟add函数销毁也一样。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

-Taco-

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

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

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

打赏作者

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

抵扣说明:

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

余额充值