函数栈帧的创建和销毁

函数每一次调用都会在栈区上开辟空间;在介绍这一部分知识时,我们需要了解一些汇编语言的基础知识,比如常用指令的作用,同时还要了解常用寄存器的作用。

一:常用汇编指令和寄存器

push指令:它首先减少esp的值,再将源操作数复制到栈地址32位平台上,esp每次减少4字节。

pop指令:它首先把esp指向的栈元素内容复制到一个操作数中,再增加esp的值。在32位平台上,esp每次增加4字节。

mov指令: 用于将一个数据从源地址传送到目标地址,源操作地址的内容不变。

sub指令:减操作指令,从寄存器中减去表示的数值,并将结果保存到目标寄存器中

add指令:用于将两个运算子相加,并将结果写入第一个运算子。

ret指令:用于终止当前函数的执行,将运行权交还给上层函数。也就是,当前函数的帧将被回收。

call指令:将程序下一条指令的位置的IP压入堆栈中,并转移到调用的子程序。

 二:main()函数栈帧的创建

1.main()函数的汇编代码

 

2.main()函数部分代码执行

main()函数在运行前也是由其他的函数来调用。而且栈区的地址是由高地址向低地址开辟。

 (1)步骤1

 push叫做压栈,在栈顶压入一个四字节的区域;mov:把esp的值给ebp并且移动ebp;

 (2)步骤2

 

 sub 的效果是开辟一个大小为0E4(十六进制)大小的空间,这也是为main()函数开辟的栈帧。后面的三个push是压入三个空间。

 

 (3)步骤3

 这四步是给main()函数的栈帧区域赋值,值为0CCCCCCC;所以为什么我们不进行初始的时候,直接打印会出现“烫烫烫烫....”;并且记录当前esp位置的地址;

 

 (4)创建变量

 分别给ebp-8,ebp-20;ebp-32赋值10,20,0;

 三.add函数代码执行、

1.传参

(1)存值

分别向eax和ecx寄存器里面存入地址为ebp-20(b:20)和ebp-8(a:10)的值;

这也说明了函数传参的时候是从又到左传递参数;在add函数中先传递b的值,再传递a的值;

(2)压栈

2.add()函数栈帧空间开辟

 前三步和开辟main()函数的方法类似。先压栈,再移动esp寄存器开辟函数的栈帧空间

 3.压栈和初始化

 

和main()函数初始的方法类似:

 4.赋值

 把值0存在ebp-8地址里;

 

 5.运算z=x+y;并返回z

 

 eax是一个擅长运算的寄存器;这三步的作用是把ebp+8地址的值(10)存入eax,再加上ebp+0C地址的值(20),再把值放入ebp-8地址处;

函数在传递形参时,并没有给add函数的局部变量x,y在栈区上开辟空间,是利用eax,ecx进行传参计算。

 

 6.销毁add()函数的空间

 

 pop指令叫做出栈;弹出edi,esi,ebx的空间;esp加上0CC,那么esp在栈空间上向下移动,也是销毁空间;给esp赋值为ebp,最后弹出ebp;

 

 这样的结果为ebp回到了main()函数内部;

 

四.main()函数撤销空间

 过程和add函数的撤销空间的方式类似。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

影中人lx

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

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

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

打赏作者

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

抵扣说明:

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

余额充值