函数栈帧的创建和销毁

                             函数栈帧的创建和销毁

导语: 本次讲解使用的环境是 vs2013,不要使用太高级的编译器,编译器越高级函数封装越厉害,越不容易学习和观察,在不同的编译器下,函数调用过程中栈帧的创建是略有差异的,具体细节取决于编译器。

补充知识

① 寄存器 : eax,ebx,ecx,edx(存数据) ; ebp,esp( 存地址 )

每一个函数调用,都要在栈区创建一个空间; ebp,esp这两个寄存器中存放的是地址,这两个地址是用来维护函数栈帧的。

                     在这里插入图片描述

正文:

   实验所用代码:

#include<stdio.h>

int add(int x, int y)
{
	int z = 0;

	z = x + y;
	return z;
}

int main()
{
	int a = 16;
	int b = 32;

	int c = 0;
	c = add(a, b);

	return 0;

}

1.main函数的调用

①通过查看函数栈帧,我们发现了不一样的东西

在这里插入图片描述

②接下来我们将通过一步步运行汇编代码带你走进底层,看到真实的样子

在这里插入图片描述


在这里插入图片描述


③参数是如何赋值的

在这里插入图片描述

在这里插入图片描述

2. add函数的调用

调用前要把下一条指令存起来

在这里插入图片描述

②完整的add函数汇编指令

            在这里插入图片描述

③刚进入add 函数要有类似main函数的指令

在这里插入图片描述

④add函数内进行计算

在这里插入图片描述

add函数返回,栈帧销毁

在这里插入图片描述

3.main函数的返回

在这里插入图片描述

4.遇到的困惑与解答 !

①局部变量是怎么创建的:

        首先给函数分配栈帧空间,然后对空间进行初始化,在栈帧里给局部变量分配空间

②为什么局部变量的值是随机的:

        随机值是我们初始时放进去的

③函数是怎么传参的?传参的顺序是怎么样?    

        当我们去调用函数的时候,还没有调用就已经把参数 push入栈了,从右向左push,在函数内部通过指针偏移量找到参数。

④实参和形参的关系?

        形参是实参的一份拷贝。

⑤函数调用是怎么返回的?

        调用函数之前我们就把call指令的下一条指令地址记住了压栈了,把调用这个函数的上一个函数的ebp栈帧存进去了,当函数调完要返回的时候,弹出ebp就能找到上一个函数调用的ebp指针,指针向下走的时候就能找到esp的顶。我们记住了call指令的下一条指令的地址,当我们往回返的时候就能跳转到该指令的地址,call返回的时候就能继续下一条指令,返回值是通过寄存器带回来的。

万一为函数预开辟的空间不够了怎么办

        这个编译器已经帮我们考虑好了,编译器会自动计算需要多大的空间,不可能出现不够的情况。

变量之间的存放不一定是紧挨着的,变量之间有多少空间时不确定的,取决于编译器

⑧ebp是个寄存器,pop ebp是将栈顶弹出的内容放到ebp中。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值