C语言中函数栈帧的创建于销毁

前期学习的时候,我们可能有很多疑惑?

比如:

 局部变量是怎么创建的?

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

 函数是怎么传参的?传参的顺序是什么?

 形参和实参是什么关系?

 函数的调用是怎么做的?

 函数调用结束后怎么返回的?

当我们知道函数栈帧的创建和销毁就都懂了,简单来讲就是修炼自己的内功。

进入正题

今天讲解的时候,使用环境是VS2013,不使用太高级编译器的原因是高级的编译器不容容易学习和观察。不同的编译器,函数调用过程中栈帧创建是有差异的,具体细节取决于编译器实现。

我们在理解函数栈帧之前必须先了解两个寄存器  ebp esp

edp,esp 这两个寄存器中存放的是地址

这两个地址是用户来维护函数的调用的。

接下来我们来解释一下

其实每一次函数的调用都需要为其开辟一段空间。

我们使用最简单的函数调用代码来为大家演示。

然后我为其开辟一段空间我使用简单点的方法让大家容易理解

这是一段地址我接下来给大家演示它们之间的关系

关键点拨:C语言\C++中   栈区---内存用来存放  局部变量,函数的形式参数(临时属性的变量)。  堆区---用来存放 malloc,free,calloc,realloc(动态内存管理)。 静态区---用来存放 静态内存,全局变量。

图中的esp,edp为main函数开辟了一段栈区用来维护main函数的运行,主函数从main函数开始执行

当执行到C=Add(a,b)时,函数向上执行此时esp和edp也维护着函数的调用

知识拓展:栈区的使用方法从低到高使用。

所以不难看出地址的使用是从高地址到低地址。

此时esp维护着栈顶,edp维护着栈低。

当我们在VS2013的编译器下是实现这个代码的时候我们可以了解到main的调用

接下来只展示结果,过程过于复杂。

得到结论:

调用的两个函数函数栈帧的过程如下:

接下来我们为大家演示地址使用的过程(通过调试窗口)

下面有调试的过程

通过调试观察我们不难发现地址由8变成了4,这就意味着地址从高到低进行执行。

由于地址的跳动esp与edp也向上悦动,此时esp与edp之间的空间就是为main函数开辟的了。

接下来经过压缩(push)在esp的顶上又会出现一段空间

我们观察push(压缩)的有 ebx esi edi

那么我们不难通过图示来为大家讲解

由于不断地压缩esp为了维护栈区所以也在不断的移动由刚开始的指向ebx到现在的指向edi.

那么就有一个疑问开辟的空间的地址是否可以得到呢?

我们通过调试也不难得到main函数的栈帧中的地址

接下来为大家展示在此之前大家需要了解两个单词的意思

push  压栈---给栈顶放一个元素

   pop   出栈---从栈顶删除一个元素

我们不难观察出在main函数栈帧中的地址是cc cc cc cc

有了上面的作为铺垫现在我开始真正意义上的进入正题。

我们拿 int a=10; 来为大家展示 

move   移动的意思在这里指的是把0Ah(10)放入【ebp-8】的位置

那么是如何放进去的呢,其基本原理是什么呢?

大家好好看

我们默认是四个字节,那么edp向上移动一格此时edp指向的就是edp-4 以此类推那么edp-4的上面一格就是edp-8.

我们来解释一下,在最开始我们就强调了edp,esp,是两个寄存器用来存放地址的。

那么我们就可以得到结论在 int a=10;中为a开辟的空间就是 edp-8.

后面的就按照这个思路理解

这就是局部变量的创建的过程。

现在我们来总结一下创建的过程,首先创建一个函数栈帧,在这个函数栈帧中开辟空间,

然后创建。

创建好了之后我们来研究函数的调用。使用上面的代码是Add函数。

函数调用的第一步是传参,那么是如何传参的呢?

接下来为大家讲解其过程

我们来解读一下,我们可以知道【ebp-14】的值是20(上面有讲解),此时出现了push(压栈)push    eax    这是什么意思呢?

其实很好理解来吧展示

因为压栈是在顶部给一个元素,那么我们在其顶部给个元素eax就很好理解了。

通过程序的执行又push了一个ecx.

好接下来我们继续观察程序的指令。下面展示过程

我们直接说结论吧

通过一系列的指令我们可以得出:形参就是实参的一份临时拷贝。

通过压栈的方式把参数传到栈帧里面,然后通过偏移量来找到参数。

  • 34
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值