函数在运行期间创建的局部变量、函数参数、返回数据、返回地址都存放在栈区,而栈区又是程序地址空间的一块区域,所以先了解一下程序的地址空间!
从下到上分别是程序代码区、文字常量区、全局区、堆区和栈区,堆区和栈区是相对而生,这里我们把栈区单独拿出来,用一个例子来说明函数的调用过程,下面是代码部分:
#include<stdio.h>
int Add(int x,int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int c = Add(a,b);
printf("you should run here!\n");
printf("c=%d\n",c);
return 0;
}
首先了解以下三个重要的寄存器:
1.EIP -程序计数器/pc指针,存储的永远是当前cpu正在执行指令的下一条指令
2.EBP-基址寄存器,在函数的调用过程中存放了维护这个栈的栈底指针
3.ESP-栈顶寄存器,在函数的调用过程中存放了维护这个栈的栈顶指针
我用的是vc6.0编译环境,当程序调试时,main函数首先被mainCRTStarup函数调用,为main函数创建栈帧,汇编代码如下:
int main()
{
00401060 push ebp
//将ebp压栈
00401061 mov ebp,esp
//将esp赋给ebp,产生新的ebp
00401063 sub esp,4Ch
00401066 push ebx
00401067 push esi
00401068 push edi