函数栈帧

来源:互联网 发布:mac图片导出到硬盘 编辑:程序博客网 时间:2024/05/24 06:23

在调用任何一个函数时,系统都会为其分配内存空间,便于它存储临时变量或者别的一些东西,下面我就来简单介绍一下函数在调用时它的内存情况。即函数栈帧。
以此段代码为例:(此例是在vs2013下实现的)

int Add(int x, int y){    int sum = x + y;    return sum;}int main(){    int x = 10;    int y = 20;    int ret = 0;    ret = Add(x, y);    printf("%d\n", ret);    system("pause");    return 0;}

先来介绍两个寄存器:esp(栈顶指针),ebp(栈底指针)。这两个指针是来维护栈帧的范围。在调用main函数之前,这两个指针已经存在。

009B3E60  push        ebp 

这里写图片描述

009B3E61  mov         ebp,esp  009B3E63  sub         esp,0E4h  

这里写图片描述

009B3E69  push        ebx  009B3E6A  push        esi  009B3E6B  push        edi  

这里写图片描述

009B3E6C  lea         edi,[ebp-0E4h]  009B3E72  mov         ecx,39h  009B3E77  mov         eax,0CCCCCCCCh  009B3E7C  rep stos    dword ptr es:[edi]  

这段反汇编的意思是将从ebp-0E4h开始往下赋值,赋39h次0CCCCCCCCh。
这里写图片描述

这里写图片描述

    int x = 10;009B3E7E  mov         dword ptr [x],0Ah      int y = 20;009B3E85  mov         dword ptr [y],14h      int ret = 0;009B3E8C  mov         dword ptr [ret],0      ret = Add(x, y);

这里写图片描述

这里写图片描述

009B3E93  mov         eax,dword ptr [y]  009B3E96  push        eax  009B3E97  mov         ecx,dword ptr [x]  009B3E9A  push        ecx  

这里写图片描述

009B3E9B  call        _Add (09B11F4h)  

这里需注意,在执行call指令时,它会将call指令的下一条指令的地址自动压入堆栈!以便现场恢复!

009B3C00  push        ebp  

这里写图片描述

009B3C01  mov         ebp,esp  009B3C03  sub         esp,0CCh 

这里写图片描述

009B3C09  push        ebx  009B3C0A  push        esi  009B3C0B  push        edi  009B3C0C  lea         edi,[ebp-0CCh]  009B3C12  mov         ecx,33h  009B3C17  mov         eax,0CCCCCCCCh  009B3C1C  rep stos    dword ptr es:[edi]  

这里写图片描述

    int sum = x + y;009B3C1E  mov         eax,dword ptr [x]  009B3C21  add         eax,dword ptr [y]  009B3C24  mov         dword ptr [sum],eax      return sum;

此段汇编表明,在进行加法运算时,是通过寄存器eax来进行运算。
这里写图片描述

这里写图片描述

009B3C27  mov         eax,dword ptr [sum]

将sum的值赋给eax寄存器,让寄存器带回。

009B3C2A  pop         edi  009B3C2B  pop         esi  009B3C2C  pop         ebx  009B3C2D  mov         esp,ebp  009B3C2F  pop         ebp  009B3C30  ret  

这里写图片描述
执行ret指令时,会将当前esp所指向的内容弹出,并作为地址将程序执行跳转到该地址出。
这里写图片描述
009B3EA0 add esp,8 程序开始从这个地址处开始执行。

009B3EA0  add         esp,8  009B3EA3  mov         dword ptr [ret],eax 

这里写图片描述
到此,Add函数将加法运算所得到的结果通过寄存器eax返回给了main函数,存入ret中。
以上就是一个函数调用另一函数时函数栈帧所发生的变化。在对栈的使用时,是先使用高地址在使用低地址的,在调用函数传参时,从右往左传。