函数栈帧
1. 全局观:
今天我们讲的是栈区,以下的图上方是低地址,下方是高地址,跟上图相反,因此使用顺序是从下方到上方,跟上图本质上一致。
2. 函数的调用关系
ebp,esp这两个寄存器中存放的是地址,这两个地址是用来维护函数栈帧的。调用哪个函数就维护哪个函数栈帧
每一个函数调用都要在栈区开辟空间。
在VS2013中,main函数也是被其他函数调用的,调用关系如下图
3. 分析一段代码
int Add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 10;
int b = 20;
int c = 0;
c = Add(a, b);
printf("%d\n",c);
return 0;
}
分析main函数的反汇编
到此为止,main函数开辟好了
Add函数调用前的准备
因此我们讲形参是实参的一份临时拷贝
存放call指令下一条指令的地址
调用Add函数
Add返回值
每pop一次esp往下方走一次
然后ebp和esp都回到了main函数开辟后的地方,再通过存着的地址找到了call的下一条语句再继续执行
然后把return的值赋值给c
打印出来就结束啦
4. 总结
这里我们可以了解到除了蹦出去还要留下地址供自己找回来
以及为什么不初始化的变量会打印出“烫烫烫”(因为开辟时会把空间初始化成cccccccc)
还有传值调用时形参是实参的一份拷贝,因此会比传指调用占用更多空间
希望大家能更深层理解函数栈帧创建和销毁