函数栈帧的创建和销毁
导语: 本次讲解使用的环境是 vs2013,不要使用太高级的编译器,编译器越高级函数封装越厉害,越不容易学习和观察,在不同的编译器下,函数调用过程中栈帧的创建是略有差异的,具体细节取决于编译器。
补充知识
① 寄存器 : eax,ebx,ecx,edx(存数据) ; ebp,esp( 存地址 )
每一个函数调用,都要在栈区创建一个空间; ebp,esp这两个寄存器中存放的是地址,这两个地址是用来维护函数栈帧的。
正文:
实验所用代码:
#include<stdio.h>
int add(int x, int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int a = 16;
int b = 32;
int c = 0;
c = add(a, b);
return 0;
}
1.main函数的调用
②接下来我们将通过一步步运行汇编代码带你走进底层,看到真实的样子
2. add函数的调用
3.main函数的返回
4.遇到的困惑与解答 !
首先给函数分配栈帧空间,然后对空间进行初始化,在栈帧里给局部变量分配空间
随机值是我们初始时放进去的
当我们去调用函数的时候,还没有调用就已经把参数 push入栈了,从右向左push,在函数内部通过指针偏移量找到参数。
调用函数之前我们就把call指令的下一条指令地址记住了压栈了,把调用这个函数的上一个函数的ebp栈帧存进去了,当函数调完要返回的时候,弹出ebp就能找到上一个函数调用的ebp指针,指针向下走的时候就能找到esp的顶。我们记住了call指令的下一条指令的地址,当我们往回返的时候就能跳转到该指令的地址,call返回的时候就能继续下一条指令,返回值是通过寄存器带回来的。
这个编译器已经帮我们考虑好了,编译器会自动计算需要多大的空间,不可能出现不够的情况。
⑦变量之间的存放不一定是紧挨着的,变量之间有多少空间时不确定的,取决于编译器。