以下面一段代码为例,说一说函数的调用过程,栈帧的创建与销毁。
这段代码要在VC6.0下调试,因为VC6.0对这部分的处理简单些,利于学习使用。
#include<stdio.h>
int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 258;
int b = 20;
int ret = Add(a, b);
printf("ret = %d\n", ret);
return 0;
}
调试以上代码,看调用堆栈窗口,我们可以看到main函数在 __tmainCRTStartup函数中被调用,而__tmainCRTStartup函数是在mainCRTStartup中被调用。
每一次函数调用都是一个过程,这个过程我们叫做:函数的调用过程。
这个过程要为函数开辟栈空间,用于本次函数调用中临时变量的保存、调用现场的保护。这块栈空间我们称之为函数栈帧。
想要了解清楚函数的调用过程,栈帧是如何创建和销毁的,首先要了解一些汇编的知识。
ebp和esp两个寄存器,在函数调用过程中这两个寄存器存放了维护这个栈的栈底和栈顶的指针。
例如:调用main函数,我们为main函数分配栈帧空间,栈帧维护如下:
ebp存放指向栈帧栈底的地址,esp存放指向栈帧栈顶的地址。
下面来看调试模式下的反汇编窗口:(以下截图均来自VS2013,因博主木有安装vc6.0)
1.从main函数开始,先来看main函数栈帧的创建
2. 2.接下来看Add函数的调用
执行call指令,按下F11,如下:
再按F11,来到Add函数的执行代码处:
接下来是Add函数返回部分,Add函数栈帧销毁过程:
以上就是函数调用的全部过程。