要理解函数栈帧,就必须要明白两个寄存器esp和ebp

首先先贴一段百度百科关于寄存器的定义,但对于理解函数栈帧来说,我们只要大概明白两个寄存器esp和ebp。寄存器是在cpu上的一个相对其他存储空间较小的存储器,它能快速的读取和存储数据,而我们所需要的两个寄存器就是通过存储地址来维护函数
每一个函数的创建都需要在栈区开辟一个空间
而我们的两个寄存器,esp存储函数的在栈区的栈顶地址,ebp存储栈底的地址,这样通过两个地址我们就可以对其中的栈区进去维护在其中存放变量,从而达到我们函数的功能。
于是我们通过开辟一个栈空间,为一个函数就留好了属于它自己的舞台,每一个函数都要属于它们自己的栈空间,而寄存器却只有两个所以当我们调用不同的函数时,我们就可以很好的解释为什么其他函数的地址就找不见了(因为寄存器只能对同时一个函数进行维护)函数的独立性就可以解释了。
下面,我们就来探讨传值调用和传址调用本质吧
int main()
{
int a=3,b=4;
int ret=Add(a,b);//以调用函数Add实现求加法来举例
return 0;
}
当编译器读到这一步时,此时,寄存器还在维护主函数中并已经对a,b两个变量在栈区开辟一个地址空间存储它们的值(中间的其他过程为了陈述方便进行省略,请谅解)

当编译器将要读取Add函数这一步时,先会用其他寄存器将a,b的值暂时存储起来,就像这样

当我们进入add函数中时寄存器也开始维护Add函数,在执行这个之前要将主函数的位置存下,以便调用结束时返回主函数

让我们先忘记主函数吧,现在寄存器眼里只有Add函数了。
注意函数中的形参是不会存进Add函数的栈区的,而是在栈区中创建一个空间来保存返回值的值,新建的变量空间由高到低创建(所有函数都是按照这个顺序存放变量的,包括主函数)

进行完存值后,我们所需的新参便从原来的寄存器中读取值返回到返回值的空间中,最后将返回值压栈到eax中存储。然后将Add函数回收再将ebp的地址给esp,让头返回,然后将尾ebp弹出,到呢个地址处,ebp就返回到函数中了,调用Add函数结束,最后ret的值等于eax中存储的值。
上述仅代表本人浅显的见解,如有错误欢迎大家的指正!
925





