来源:
1、《代码揭秘》第六章函数与函数调用
2、http://blog.csdn.net/zhuliting/article/details/6839233
引入话题:
局部变量是动态分配的-》降低了运行效率-》为了使得动态分配的代价最小化,编译器试着每次为一大组局部变量分配空间,而不是每次为单独的一个变量分配空间
-》对于函数来说,被分配给每次函数调用的那一大块内存叫作“活动记录” (”活动记录“在函数调用时被创建,当函数返回时被销毁)
”活动记录“存放在栈中,栈指针和帧指针界定了活动记录的范围。其中栈指针始终指向栈顶,帧指针为一个活动记录的开始地址。
在汇编语言中,帧指针存放在EBP寄存器中,栈指针存放在ESP寄存器中。
参考:http://www.cnblogs.com/shitouer/archive/2010/04/05/1704554.html
#include <stdio.h> int sum(int a,int b,int m,int n)
{
return a+b;
} int main()
{
int result = sum(1,2,3,4);
}
使用反汇编技术分析上述代码见上述参考博客。下面主要是根据反汇编结果给出的栈图
一般进入函数后,要完成3步:
1、旧的帧指针入栈
2、EBP = ESP;
3、栈指针减小
阴影部分为main函数开始时的ESP和EBP。进入main函数后,首先,旧的帧指针入栈(旧的EBP为0x0012FF88),因为指针占4个字节,所以ESP由原来的
0x0012FF4c变为0x0012FF48.
接着push ebx push esi push edi
以及lea edi, [ebp-44h]
接着程序运行到 int result = sum(1,2,3,4);
即:进入函数sum(....)中,此时”活动记录“变为函数sum的活动记录。
4个参数入栈,栈中情况变为如下图所示。
接着,保存返回地址(在我做的实验中,返回地址为0x00401085)
接着将旧的EBP入栈,保存起来,这个旧的帧指针是main函数活动记录的帧指针:0x0012FF48
然后将EBP=ESP
接着sum函数的活动记录的ESP减小
int sum(int a,int b,int m,int n)
{
return a+b;
}
在sum函数中,如何找到a+b,即1+2;
由上图可见,EBP+8所在的位置为1,EBP+12所在的位置为2.
下篇图解函数函数返回时的问题。