1.4函数栈帧的销毁
知识点:
当我们进入到ADD函数后,要经历和main函数一样的函数栈帧创建过程:
具体我就不再讲述了和main函数一样的操作(ebp压栈、改变esp、再ebx esi edi压栈、再将开辟的空间赋值成cccccccc)
细节:
进入到ADD函数的语法部分
1.首先对z的初始化
第一个变量的位置ebp-8处存放z = 0(具体看下图)
2.其次进行z = x + y 的赋值
先将之前压好的数据(ebp+8)移动到寄存器eax上
再加上另一个之前压好的值(ebp + c处的数据( c是十六进制就是表示ebp + 12))
最后再把这个寄存器上的值存进z = 5(具体看下图)
3.最后返回
再把z位置上的值(ebp-8)存放到eax上(如果不存的话当栈帧的销毁会导致数据的丢失)(具体看下图)
说了这这么多上面都是在讲述一些汇编代码,
下面才是一个栈帧的销毁
1、首先将edi esi ebx 这些之前压栈的进行出栈操作(具体看下图)
2、然后把esp移动到ebp所指向的位置(ADD的栈底)
3、然后后因为ebp的出栈,所以会让ebp返回之前函数的底部(因为一开始对main函数的ebp进行了压栈,会把压栈里的值附给此处的ebp)
4、然后esp因为ebp的出栈就会指向一开始存好的call指向下一条指令的地址所压的栈上
5、当进行ret会把该处进行pop处理所以esp就会指向之前压栈的两个形参ecx、eax,而程序会得到了6、call指令的下一条指令的地址就会接着从下一条指令开始往下执行
回来后再对esp + 8 就会重新指回main函数的顶部
最后再把存放在eax中的z的值存放到c开辟的空间处
后面再进行printf的打印以及mian函数栈帧的摧毁即可
对此就不再过多的追究了都是一些汇编代码的问题以及和ADD函数一样的栈帧的摧毁问题
2.到了此处我们需要学习到的是:
2.1变量是如何创建的创建?
先通过ebp、esp两个寄存器进行压栈和esp的减去一定的值再对该区初始化后在这开辟好的栈帧空间内分配一定空间给该局部变量
2.2为什么变量不初始化会是随机值?
因为在局部变量放进去之前,已经对该区域的数值进行了随机的存放,如果该变量没有初始化,那么该变量的值就等于当初随机存放好的值(cc cc cc cc)(所以我们应该初始化把随机进行覆盖)
2.3函数是怎么传参的以及传参的顺序是什么?
当传参时是将参数从右向左的把参数进行压栈压到栈顶,后面直接从ebp+8 ..... 进行取数据
2.4形参和实参的关系是?
因为是压栈的,压栈就意味着开辟一块新的空间只是把实参的数据拷贝了过来,所以说在传值调用时改变形参不影响实参
2.5函数的调用时怎么实现的?
之前的call、ret来进行的(具体上面已经写过)
2.6调用结束后是怎么返回的?
通过寄存器eax进行保存返回的结果