函数的调用过程,栈帧的创建和销毁
2017-12-07 14:32
323 查看
栈帧就是一个函数执行的环境:函数参数、函数的局部变量、函数执行完后返回到哪里等等.栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。
下图为程序存储空间
入栈:push eax
出栈:pop eax
代码:
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的栈帧。
下图为程序存储空间
入栈: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的栈帧。
相关文章推荐
- 函数的调用过程,栈帧的创建和销毁。
- 函数调用过程,栈帧的创建和销毁
- 函数的调用过程,栈帧的创建和销毁
- 函数的调用过程、栈帧的创建以及销毁
- 谈谈函数的调用过程,栈帧的创建和销毁。
- 函数调用过程,栈帧的创建和销毁
- 浅谈函数的调用过程,栈帧的创建以及销毁
- 【C】函数的调用过程,栈帧的创建和销毁
- 函数的调用过程,栈帧的创建和销毁。
- 函数的调用过程,栈帧的创建与销毁
- 谈谈函数的调用过程,栈帧的创建和销毁。
- 函数的调用过程,栈帧的创建和销毁
- 函数的调用过程,栈帧的创建和销毁
- 函数的调用过程 栈帧的创建和销毁
- 函数调用的具体过程以及栈帧的创建和销毁
- 函数的调用过程(栈帧的创建和销毁)
- 浅谈函数的调用过程,栈帧的创建和销毁,附图讲解
- 函数的调用(栈帧的创建和销毁)
- 函数的调用过程(函数调用栈帧的创建)
- 浅谈函数的调用,栈帧的创建和销毁