绪论
书接上回,上回我们已经将C语言的所有知识点进行了总结归纳到同一个思维导图中,而本章是一个番外篇,将具体讲述一些更深入的知识。
话不多说安全带系好,发车啦(建议电脑观看)。
思维导图:
要XMind思维导图的话可以私信哈
目录
1.函数栈帧的创建和销毁
1.1寄存器
1.2创建函数栈帧
1.3程序进程中的汇编代码
1.4函数栈帧的销毁
2.到了此处我们需要学习到的是:
2.1变量是如何创建的创建?
2.2为什么变量不初始化会是随机值?
2.3函数是怎么传参的以及传参的顺序是什么?
2.4形参和实参的关系是?
2.5函数的调用时怎么实现的?
2.6调用结束后是怎么返回的?
1.函数栈帧的创建和销毁
函数栈帧的创建和销毁在不同的编译器底下的实现都不一样(越高级的编译器越复杂,但其基本逻辑是一样的)
1.1寄存器
知识点:
寄存器是具有存储功能的一个cup内的原件
在C语言中有着多个寄存器(eax、ebx、ecx、edx、ebp、esp)但各自有着不同的功能
对于函数栈帧的创建和销毁主要要看的是下面这两个寄存器
esp(栈顶指针),ebp(栈底指针) 这两个寄存器中存放的是地址用来维护正在调用的函数的函数栈帧
细节(注意点):
在每一次函数的调用过程中都会在栈帧上开辟一块空间,对于每个开辟的空间就被称作该函数的函数栈帧(如ADD函数的函数栈帧)
栈区空间的使用习惯是先使用高地址再使用低地址
main主函数也是被其他函数调用的(当进入到主函数时esp、ebp就会指向主函数所借用的空间(指向正在进行的函数)具体细节我们就不再过多的追溯了)
1.2创建函数栈帧
知识点:
当进入到调用的函数的函数栈帧他会
先进行push压栈,并且把寄存器ebp指向所压的空间
然后再将esp指向和ebp一样的位置(具体看下图)
再将esp减去将要开辟的空间大小(每个函数减的大小(所开辟的空间大小)都可能不一样这取决于编译器。附:因为函数栈帧的使用习惯是先使用高地址再使用低地址的所以是减才能让寄存器所指向的位置往上走)(具体看下图)
再然后会连续push(压栈)三个寄存器进来ebx、esi、edi(这具体的细节不用去了解)
最后的4个个步骤可以概括为将所开的空间(从esp到ebp)全部置为cc cc cc cc(具体看下图)
1.3程序进程中的汇编代码
知识点:
1.当成功创建了一个栈帧后,我们对栈帧内的代码执行,此处先对 int a ,b 的初始化
具体是在ebp-8和ebp-20的位置进行mov操作,将2存放到ebp-8,将3放到ebp-20(所以说变量的创建是从栈帧中的ebp-8处开始创建第一个的,并且每次开辟的空间和上一次变量开辟的位置中间相差2个整形的空间,地址相差12)(具体看下图)
2.再到ADD函数的调用
对于前四步可以概括为从右往左的把参数进行压栈操作(将参数压栈到栈顶)(具体看下图)
3.call调用该函数,并且记住call指令后的下一条指令的地址进行压栈,后面可以通过压栈内的地址就可以找回然后继续往下进行程序(具体看下图)