【11 详解函数栈帧】

目录

  1. 源码
  2. 分析
  3. 全过程图示
  4. 总结

函数栈帧讲解

函数栈帧初解

1. 源码

函数栈帧包括了函数的调用,栈的开辟,参数的使用,栈空间的分配等,理解了函数栈帧,有助于我们写出更规范的代码,了解和观察内存的使用情况,本文将基于上一章函数栈帧的解释,更详细,复杂的讲解函数栈帧的情况,有些简单的过程上一章已经一句一句的分析了,将一笔带过,讲解重要的部分

环境基于 vc6.0

#include <stdio.h>

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(),其中涉及有参无参的多种情况,较为简单,当学会了简单代码的分析,就可以看更复杂的

2. 分析

按F10进入调试,函数运行到main函数左花的位置,打开反汇编和内存监视窗口,内存窗口取main函数的a变量地址,监视窗口取栈顶和栈底,开始观察

在这里插入图片描述
栈窗口可以看出main函数的上一层调用函数maincrt,调用了main函数

main函数

汇编代码

在这里插入图片描述
在这里插入图片描述

监视窗口

在这里插入图片描述
此时显示maincrt函数的栈顶和栈底

图示

在这里插入图片描述
上面的代码完成了main函数的栈空间开辟和初始化

图示

在这里插入图片描述

汇编代码

在这里插入图片描述
现在开始mian函数中代码的执行

在这里插入图片描述
图示

在这里插入图片描述

fun1函数

汇编代码在这里插入图片描述
开始为调用fun1函数准备,此时栈顶压入调用fun1函数下一条代码的位置

图示

在这里插入图片描述

main内存

在这里插入图片描述
上面颜色依次为,红色部分是mian函数的三个参数,粉红是maincrt的返回地址,深红是maincrt的栈底,深绿部分局部变量空间,橙色部分是保存的寄存器环境,上面蓝色部分是用来传递参数的两个寄存器eax和ecx

之后执行跳转到调用fun1函数的地址,按F11跟进

在这里插入图片描述汇编代码

在这里插入图片描述

上面部分和main函数空间开辟一样

图示

在这里插入图片描述
汇编代码

在这里插入图片描述
在这里插入图片描述
执行fun1函数的代码,代码在汇编中已显示

图示

在这里插入图片描述

fun2函数

汇编

在这里插入图片描述
传递参数,压入返回地址004010fc,调用函数

图示

在这里插入图片描述

fun1内存

在这里插入图片描述
从下往上
红色: 参数
粉红: 返回地址
深红: main函数栈底
绿色: 申请的空间
橙色: 寄存器环境

汇编

在这里插入图片描述
开辟fun2函数空间

图示

在这里插入图片描述

汇编

在这里插入图片描述
执行代码

fun3函数

汇编

在这里插入图片描述
这里调用了一个函数,该函数的功能是将st0寄存器的浮点数去尾取0,也就是吧浮点数强转为int,这里暂略过该过程,从下一条开始

传递浮点去整结果和常量参数3,继续压入返回地址,开始函数调用开辟空间

图示

在这里插入图片描述
汇编

在这里插入图片描述

图示

在这里插入图片描述
汇编

在这里插入图片描述
取得返回地址,函数返回,释放空间,edcel调用约定调用方清理参数

在这里插入图片描述
返回到401095,并清理参数空间

图示

在这里插入图片描述
汇编

在这里插入图片描述
弹出寄存器,释放局部变量空间,在debug模式下,函数有时会调用chkesp函数,该函数的功能是用来检查栈是否平衡,如果不平衡会报错,此处先略过,栈顶到返回地址处,栈底回到fun1函数栈底

图示

在这里插入图片描述

汇编

在这里插入图片描述
继续回到上一层

图示

在这里插入图片描述
汇编

在这里插入图片描述
此时将返回到maincrt函数,之后过程相似,不做赘述

3. 全过程图示

在这里插入图片描述

4, 总结

  1. edecl调用约定从右往左传递参数,参数空间由调用方清理
  2. 函数返回值一般由eax寄存器带回
  3. debug模式局部变量空间会初始化为cccccccc,申请的空间大于需要使用的
  4. 变量空间释放并不会使数据发生变化,只会将空间标位未使用,然后挪栈的位置。所以内存仍有残留数据
  • 30
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值