函数调用过程中产生的栈帧

在c语言中编译的程序占用的内存分为一下几个部分:

  1、栈区(stack)2、堆区(heap)3、全局区(静态区)(static)4、字符常量区 5、代码区(code)

如图所示:  

 


这篇博客主要描述其中的栈区。

在函数的调用过程中,要为函数开辟空间,用于本次函数的调用中临时变量保存、现场保护。这块栈空间我们称之为函数的栈帧。

先要了解 几个寄存器  :  ESP  栈顶寄存器      EBP栈底寄存器(基址寄存器) EIP 程序计数器:放当前正在执行指令的下一条指令的内容

以一个简单的程序来描述函数的栈帧。

#include <stdio.h>
#include <windows.h>
int Add(int x,int y)
{
   int z=0;
   z=x+y;
   return z;
}
int main()

{
   int a=0xaaaaaaaa;
   int b=0xbbbbbbbb;
   int ret=Add(a,b);
   printf("ret=%d\n",ret);
   system("pause");
   return 0;
}

分段转入此程序的汇编代码中:


在此段代码中,栈结构如图所示。    在此图中,我们发现函数形参实例化是从右向左的。

将ecx中内容入栈,接来下就是call命令,call命令有两个作用:

      ①将当前汇编地址的下一条地址保存在栈上,便于恢复。

      ②跳转至目标函数的入口地址处。

   

call命令后,由汇编代码可以看到,跳到了  目标地址 00401005。


此段汇编代码,则是函数内部的调用过程。  

对应栈上的图,相对比较好理解。



此时函数的栈帧已经形成,就是  粗体EIP,ESP所指向的内容。


接下来就是ret指令,有两个功能:

      ①  将之前保存的函数值的返回地址进行出栈,即00401093出栈

      ② 将弹出的地址放入EIP。

按下F11后,我们跳转至了  00401093,如图:


也就是  此时ESP指向红线处:




经过此代码,函数调用过程中产生的临时变量全部清空,即临时变量随用随丢,由图可证。



函数调用完成,返回值也附给main函数。

进过函数调用产生的栈帧,亦可以得出两个结论。

一、函数形参形成是随用随丢的。

二、函数形参调用是从右至左形成的。


仅以个人理解作此文章,难免有遗漏或不足之处,欢迎随时指出问题!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值