函数栈帧的创建和销毁

       

目录

 函数栈帧的创建

函数内部的实现

函数调用结束后返回值的返回和栈帧的销毁


        "函数栈帧的创建和销毁"这个知识点使我知道我初学程序语言时打印烫烫烫乱码的原因,另外也让我搞懂了一些代码内部的工作方式,函数栈帧的创建和销毁无疑是一种修炼内功的方式。

        这篇内容看上去很复杂,一串连下来,其实很容易掌握,所以需要耐心,干货多多,细节饱满。

        函数栈帧大概分为创建、内部实现和销毁,ebp称为栈底指针,esp称为栈顶指针,共同维护一块函数栈帧,esp再次使用时向上移动且移动到栈顶,ebp的再次使用也是需要修改的。

        eax是用来存放需要修改的值,edi是用来存放需要修改(一块空间所有的值)的地址,ebx是用来存放从edi地址向下需要修改值的次数,连起来就是将edi地址向下ecx次全部初始化为eax的值,eax,ebx,ecx,edx都属于寄存器。

        压栈是在栈顶压,即push,出栈是在栈顶出,即pop,这些寄存器就是压栈来搞一块属于自己的地址。

        这里我用VS2019演示实际的函数栈帧的创建和销毁,VS2013更好,版本越高简化的越多,底部具体步骤相比更简单。

        调用堆栈可以看函数与函数之间的调用关系,比如main函数是由__mainCRTstartup调用(vs2013可以查看)

 

 函数栈帧的创建

        调试时右键代码区域转到反汇编,可以查看汇编代码

为了查看的更细致,右键将显示符号名关掉

从上往下,一步一步来。

push压栈ebp,在__mainCRTstartup栈顶压栈,mov是后者移动到前者,因为esp和ebp都是指针变量,所以将esp的值改为ebp的值,sub是前者减后者,esp-0E4h,逻辑上的一块栈帧,高地址在下,低地址在上,这里esp向上移动,栈顶压栈ebx,esi,edi,随后lea是指load effective address加载有效地址,rep stos的作用是edi加载地址向下ecx次全部初始化为0CCCCCCCCh,这就是打印出烫烫烫乱码的原因,其中dword的word是两个字节,dword是四个字节,其次发现寄存器并不是特定的需要存特定的值,call意思为调用

 内存窗口发现函数栈帧的创建已经成功了,一块很大的区域(这里只是展示了一部分)全部初始化为cccccccc,上面的call调用的不必关心。

继续往下走~

函数内部的实现

 ebp-8,就是栈底指针与我们要用的4个字节(dword)的指针之间隔了8个字节,相当于栈底指针是一块,向上隔一块,0Ah16进制,A*16^0=10,所以ebp-8的地址就是为a所用的,b和c也就迎刃而解了

 其次,压栈存放20的eax,压栈存放10的ecx,F11调用Add函数

 压栈ebp,把原来esp的值传给ebp,这里画图演示,esp自动向上移动

 return x+y上面的都是函数栈帧的创建,ebp+8就是ecx,20,ebp+0ch(12)就是上图eax,10,这里足以证明形参是实参的一份临时拷贝,不会影响实参的值,不会在函数内部新开辟一块空间,eax最后等于30,寄存器不会销毁,所以这就是为什么返回值不会销毁的原因。

函数调用结束后返回值的返回和栈帧的销毁

vs2013

 vs2019

一条指令一条指令走,pop出栈edi、esi、ebx,回过头看Add函数调用时的汇编代码第三行,再看0c0h,一目了然,这个需要思考一下,其实跟着代码一步一步走,就是把Add函数栈帧销毁了而已。

 函数栈帧用完后就销毁了,其次就是看返回值eax是怎么执行的

esp+8指到存放eax的地址处

 ebp-20就是存放c的地址,把c mov 成eax(30)就ok了。

  • 36
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值