您的位置:首页 > 其它

函数的调用过程,栈帧的创建和销毁

2017-12-07 14:32 323 查看
栈帧就是一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里等等.栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。

下图为程序存储空间



入栈:push eax

出栈:pop eax

代码:
#include<stdio.h>
Add(int a,int b)
{
int z=a+b;
return z;
}

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

}
在上代码中函数Add()执行时,栈的调用过程:

main的栈桢:



main函数的栈桢为从低地址esp到高地址ebp这块区域.在调用Add函数时过程大致为

push x;

push y.;将形参压入栈中

call Add;调用Add函数。将返回值地址填入栈。并跳转到Add函数.



跳转后,Add的汇编大致为

push ebp 因为Add为一个新的函数,需要自己的栈桢 ,则将main函数的栈底压栈操作.因为main栈顶为Add栈底则不操作.

mov ebp esp 上一个栈桢的顶部为此函数的底部



到这里,新的栈桢Add栈桢开始了



sub esp,8;int a,b;这里

这里声明了两个int,所以esp减小8个字节来为a,b分配空间

          mov dword ptr [esp+4], [ebp+12];  a=m

          mov dword ptr [esp], [ebp+8]; b=n     

   这样,栈的情况变为:

ret 8   ;  返回,然后8是什么意思呢,就是参数占用的字节数,当返回后,esp-8,释放参数m,n的空间

 

由此可见,通过ebp,能够很容易定位到上面的参数。当从func函数返回时,首先esp移动到栈帧底部(即释放局部变量),然后把上一个函数的栈帧底部指针弹出到ebp,再弹出返回地址到cs:ip上,esp继续移动划过参数,这样,ebp,esp就回到了调用函数前的状态,即现在恢复了原来的main的栈帧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: