函数栈帧初解
函数栈帧包括了函数的调用,栈的开辟,参数的使用,栈空间的分配等,理解了函数栈帧,有助于我们写出更规范的代码,了解和观察内存的使用情况,本文将基于上一章函数栈帧的解释,更详细,复杂的讲解函数栈帧的情况,有些简单的过程上一章已经一句一句的分析了,将一笔带过,讲解重要的部分
环境基于 vc6.0
#include
int fun3(int x,int y)
{
return x+y;
}
void fun2(int x,float y)
{
float fcnt=0;
fcnt=x+y;
fun3(3,(int)fcnt);
}
int fun1(int x,int y)
{
int z=0;
float f=3.5f;
z=x+y;
fun2(z,f);
return z;
}
int main()
{
int a=5;
int b=6;
fun1(a,b);
}
源码有三层函数调用,分别是fun1(),fun2(),fun3(),其中涉及有参无参的多种情况,较为简单,当学会了简单代码的分析,就可以看更复杂的
按F10进入调试,函数运行到main函数左花的位置,打开反汇编和内存监视窗口,内存窗口取main函数的a变量地址,监视窗口取栈顶和栈底,开始观察
栈窗口可以看出main函数的上一层调用函数maincrt,调用了main函数
汇编代码
监视窗口
图示
图示
汇编代码
开始为调用fun1函数准备,此时栈顶压入调用fun1函数下一条代码的位置
图示
main内存
上面颜色依次为,红色部分是mian函数的三个参数,粉红是maincrt的返回地址,深红是maincrt的栈底,深绿部分局部变量空间,橙色部分是保存的寄存器环境,上面蓝色部分是用来传递参数的两个寄存器eax和ecx
之后执行跳转到调用fun1函数的地址,按F11跟进
上面部分和main函数空间开辟一样
图示
图示
汇编
图示
fun1内存
从下往上
红色: 参数
粉红: 返回地址
深红: main函数栈底
绿色: 申请的空间
橙色: 寄存器环境
汇编
图示
汇编
汇编
这里调用了一个函数,该函数的功能是将st0寄存器的浮点数去尾取0,也就是吧浮点数强转为int,这里暂略过该过程,从下一条开始
传递浮点去整结果和常量参数3,继续压入返回地址,开始函数调用开辟空间
图示
图示
取得返回地址,函数返回,释放空间,edcel调用约定调用方清理参数
图示
弹出寄存器,释放局部变量空间,在debug模式下,函数有时会调用chkesp函数,该函数的功能是用来检查栈是否平衡,如果不平衡会报错,此处先略过,栈顶到返回地址处,栈底回到fun1函数栈底
图示
汇编
图示