我们在开始学习函数栈帧的创建与销毁之前,要先了解一下这几个寄存器:
?
?这里面eax, ebx, ecx是通用寄存器,保存临时数据;
eip是指令寄存器,保存当前指令的下一条指令的地址。
这里面最重要的是esp,ebp这两个寄存器。?我们要了解函数栈帧,就必须了解esp,ebp这两个寄存器。esp,ebp两个寄存器里面存放的都是地址。这里面esp是栈顶寄存器,保存的是函数栈帧的栈顶地址。ebp是栈底寄存器,保存的是函数栈帧的栈底地址。esp与ebp共同维护着函数的栈帧空间。
如图代码?
?
我们应该知道,每一次函数的调用,都要为本函数开辟新的空间,这就是函数的栈帧空间。并且该空间被栈顶栈底寄存器所维护。注意,栈底栈顶寄存器内部只保存一个地址。所以只能维护一个空间。比如如果在调用main函数,那栈底栈顶寄存器就是在维护main函数的栈帧空间。但是如果main函数正在调用另一个函数Add,?那栈底栈顶寄存器就正在维护Add函数的栈帧空间。等到Add结束调用,栈底栈顶寄存器重新维护main函数栈帧空间。
下图为本函数Add没有被调用前的esp,ebp维护栈帧情况
下图为main函数调用Add时的esp,ebp维护栈帧图?
接下来我们来看main函数是怎么被调用的。首先这需要用到函数堆栈?,先进行调试,点击f10,然后不要动。打开调用栈堆,右击显示外部代码。然后可以看到以下信息:
?
然后,由前面的基础知识我们知道,invoke_main函数会有自己的栈帧空间,而main函数同样有自己的栈帧空间,Add函数也有自己的栈帧空间。?
那么我们就可以想到,在main函数被调用之前应该是这样的
?
现在我们进行继续程序调试。右击反汇编:
?
?
?
?
?
?