函数调用堆栈

来源:互联网 发布:淘宝旺旺权重值查询 编辑:程序博客网 时间:2024/06/06 04:07

一、栈
1、传统的栈:被定义为一个特殊的容器,用户可以将数据压入栈中,也可以将压入
       栈中的数据弹出,但必须遵守一条规则:先进后出。
2、计算机系统中的栈:是一个有以上属性的动态内存区域,压栈操作使得栈增大,
       弹出操作使栈减小。栈通常是向下增长的。
3、 最重要的是栈保存了一个函数调用所需的维护信息,这通常被称为堆栈帧。
二、函数调用堆栈过程
           函数调用堆栈过程书上从反汇编函数去一步一步分析的,我这儿我想从压栈
     和清栈两方面去总结。
     压栈:
     对调用方函数来说:
     1) 压入形参变量的地址和值;
     2) 压入函数调用返回后要执行的指令的地址;
     对被调用函数来说:
     1) 压入调用函数的栈底指针,把栈底指针寄存器指向被调用函数的栈底;
     2) 开辟被调用函数的栈帧大小,并初始化为cc;
     清栈:
     对调用函数来说:
     1) 清理形参变量的内存;
     对被调用函数来说:
     1) 清理被调用函数开辟的栈帧大小;
     2) 回退栈底指针到调用函数的栈底;
     3) 把回退到调用函数要执行的指令地址给pc寄存器;
三、举例
       下面写一个简单的程序来解释一下函数调用堆栈过程:函数的活动记录用
   ebp和esp这两个寄存器(帧指针)规定范围,esp始终指向栈的顶部,ebp指向
   函数活动记录的一个固定位置。下面sum()函数为被调用函数,main()为调用方函
   数。

int sum(int a,int b){    int tmp=0;    tmp = a+b;    return tmp;}int main(){    int a = 10;    int b = 20;    int ret = 0;    ret = sum(a,b);    printf("%d\n",ret);    return 0;}

从main()开始执行,下面是压栈过程:
这里写图片描述
压栈过程是从下到上,清栈自然是从上到下。
sum()函数执行完函数返回时,开始清栈:
     1) 清理sum()开辟的栈帧大小,move esp;
     2) pop ebp:从栈中恢复保存的ebp的值,ebp回到main()的栈底;
     3) ret:从栈中获得返回地址,并跳转到该位置。
     4) return 之后esp指向最开始形参a的位置。