版权声明:Oce2ns的大板 https://blog.csdn.net/weixin_39392653/article/details/81265889
函数可以大大减少我们程序的代码量,使代码写起来更加的简洁,使代码思路更加清晰。是我们程序猿在编写代码时必不可少的。
那么函数的调用过程就非常的重要,今天让我们来从一个深的角度去了解一下函数的调用过程。
函数的调用过程也可以叫做栈帧
栈帧的定义是:栈帧也叫过程活动记录,是编译器用来实现过程/函数调用的一种数据结构。
每一次函数的调用,都会在内存中为自己申请一块空间,这个空间就叫函数运行时堆栈,也就是栈帧。
这块空间就像栈一样,都需要去维护,栈顶又寄存器ESP去维护,栈底呢就又寄存器EBP去维护。
接下来我们写一个简单的代码,去更加具体的了解我们的函数调用过程。
#include<stdio.h>
int main()
{
int i = 20;
int j = 30;
int k = 0;
k = Add(i,j);
printf("%d\n",k);
return 0;
}
int Add(int x,int y)
{//主函数调用Add函数去实现加法的功能
int z = 0;
z = x + y;
return z;
}
打开调试,进入调用堆栈,看看函数的调用逻辑。
根据内存中栈的特点是由低到高,我们看出,main函数是被mainCRTStartup函数调用。打开反汇编代码。在进去main函数到开始我们的代码前有这样一段反汇编代码。
我们把这段反汇编代码用图像形象的描述一下。
我们把E4转化成十进制,就是228,也就是说,把EBP-228的位置的地址给EDI,然后从EDI开始向高地址存放CCCCCCCC,一次4个字节,存放39次,十进制的57次,大小正好也是228.就是把这E4的空间大小,放57个CCCCCC进去,每个4字节。
看一下内存,我们看一下这样的结果,是不是我们所说的样子
然后我们接着看反汇编代码
继续画图
进入CALL指令,我们就进入的Add函数的内部
我们发现和调用main函数前,的准备工作几乎是一致的。那就说明刚才main函数开始前的操作,是开辟函数空间时的准备工作。