前言:
?? 在我们前期学习C语言时,你是否曾产生过很多困惑?
💭 比如:局部变量是怎么创建出来的?因为局部变量的值是随机值,我们建议将它初始化,那么为什么局部变量的值是随机值?函数是如何传递参数的?传参的顺序又是怎样的?形参和实参是什么样的关系? 函数的调用是怎样的一个过程?函数调用结束后是怎么返回的?
💡? 如果这些问题 "成功" 难住了你,并且你好奇这到底是为什么,建议仔细阅读这篇文章,我们将讲解函数栈帧的创建和销毁。学习了函数的栈帧和销毁后,这些问题自然就能迎刃而解,而且还能增加自己的内功,对于后期学习更多的知识是很有帮助的!
一、预备知识
在讲解函数栈帧之前,我们先探讨该使用什么编译器来观察。其次,要想了解函数栈帧,我们还需要先了解一些必备的基础知识。
0x00 该选择何种编译器观察
📚 不要使用太高级的编辑器,因为高级的编译器中函数栈帧的过程封装得更加复杂,不容易在里面抽离出函数栈帧创建的过程。值得一提的是,在不同的编译器下函数调用过程中栈帧的创建是略有差异的,具体细节取决于编译器的实现。所以为了能够更好地观察和学习,我们将使用 VS2013 来进行学习和观察。
0x01 寄存器
? 什么是寄存器?
💡 我们在前面的章节就提到过寄存器的概念了。寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。寄存器有 eax、ebx、ecx、edx、ebp、esp等。
📚 每一个函数调用,都要在栈区上创建一个空间:
💬 测试代码:
#include <stdio.h>
int Add(int x, int y) {
return (x + y);
}
int main(void) {
int a = 10;
int b = 20;
int ret = 0;
ret = Add(a, b);
printf("%d\n", ret);
return 0;
}
📚 在 VS2013 中,main函数也是被其他函数调用的:
????? __tmainCRTStartup 👉 mainCRTstartup 👉 main
直接按 F10 开始调试,调试→窗口→反汇编
此时就可以看到汇编代码了:
未完待续
|