Hello,好久没有写博客了,前两份都是之前写的,看来最近有点懈怠,最近也得快点找回学习的状态,那今天开始我们新的讲解
在我们刚开始学习C语言的时候,不知道大家有没有困惑,比如我们在使用局部变量的时候,他是怎么创建的呢
- 为什么局部变量的值是随机值?
- 函数是怎么传参的?传参的顺是怎样的?
- 形参和实参是什么关系?
- 函数调用是怎么做的?
- 函数在调用结束后是怎么返回的?
带着这些疑问,我们开始来介绍函数栈帧的创建和销毁
先给大家普及一个知识,就是我们的寄存器
要了解我们的函数栈帧,最主要的是ebp和esp,这两个寄存器存放的是我们的地址,是来维护函数栈帧的。在我们函数调用的时候,每一次都会创建函数栈帧来维护这个函数。
#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 = 0; c = Add(a, b); printf("%d\n", c); return 0; }
我们先使用的是main函数,ebp,和esp就是来维护这个函数栈帧的,ebp我们可以认为栈低指针,esp我们可以认为栈顶指针,而我们下一次函数调用的时候是在上面开辟函数栈帧,每一次调用都会开函数调用
其实我们的main函数也是被调用的
下面我们看函数的一个反汇编
因为我们的main函数也是被调用的,所以在调用之前也会开辟一个栈帧,我么来看一下这个图
我们在看下一条指令
因为我们在调用main函数的时候进行压栈,压入一个ebp,ebp中存放的是下面那个ebp的地址,而指令中的mov,就是将esp的值给了ebp,所以其实现在esp和ebp应该指向同一个地址
图是这样的
我们在看下一步
所以我们的esp指向上面的一个位置
那就意味着现在我们给main函数开辟了一个空间,这个空间其实很大的
继续看下面指令
我们不用关心这个值是有什么用,其实也是代表寄存器的,我们先不用关心,只要知道我们push三个值进去。
压栈进去,esp也变了
下一条指令更像是初始化,其实应该是下面的三条指令,首先看我们的lea,其实它的意思就是load effective address,是加载有效地址的意思,就是将后面的【ebp-0E4h】加载到edi里面去,edi是什么,它就是我们刚刚压栈进去的值
啥意思,就是相当于在栈帧中初始化