函数调用的压栈模型对于我们学习C语言非常重要,最直观的体现在我们后面要学的函数的递归,函数的递归就充分利用的函数的压栈模型。

当函数从入口函数main函数开始执行时,编译器会将我们操作系统的运行状态,main函数的返回地址、main的参数、main函数中的变量、进行依次压栈;当main函数开始调用fa()函数时,编译器此时会将main函数的运行状态进行压栈,再将fa()函数的返回地址、fa函数的参数、fa定义变量依次压栈;当fa调用fb的时候,编译器此时会将fa函数的运行状态进行压栈,再将fb函数的返回地址、fb函数的参数、fb定义变量依次压栈。

当函数fb运行完成后,fb所有的压栈都会被编译器释放掉,编译器再从栈中接收到fa函数的运行状态后,衔接调用fb函数之前的操作,继续执行,同理,fa执行完后,编译器对main函数的处理也相同。

一个函数可以在栈上分配内存,也可以在堆上分配内存,更可以在全局区域分配内存,因此理解内存从哪里来,对于我们函数参数的传递,变量的调用异常重要。

fb函数在栈上分配的内存,不能被fa和main函数所调用,因为它会在fb函数执行完后被编译器释放掉;而fb函数使用new和malloc在堆上分配的内存或者全局区分配的内存,只要不被程序员自己释放掉,是可以被fa和main函数所调用的。

转自:https://blog.csdn.net/m0_37717595/article/details/80368411

--------------------------------------------------------------------------------------

函数压栈的过程(转 知乎)

例如:

void func_A(arg_A1, arg_A2);
void func_B(arg_B1, arg_B2);int main(int argc, char *argv[], char **envp)
{func_A(arg_A1, arg_A2);
}void func_A(arg_A1, arg_A2)
{var_A;func_B(arg_B1, arg_B2);
}void func_B(arg_B1, arg_B2)
{var_B1;var_B2;
}

在main函数调用func_A的时候,首先在自己的栈帧中压入函数返回地址,然后为func_A创建栈帧并压入系统栈;

在func_A调用func_B的时候,同样先在自己的栈帧中压入函数返回地址,然后为func_B创建新栈帧并压入系统栈;

在func_B返回时,func_B的栈帧被弹出系统栈,func_A栈帧中的返回地址被"露"在栈顶,此时处理器按照这个返回地址重新跳到func_A代码区中执行;

在func_A返回时,func_A的栈帧被弹出系统栈,main函数栈帧中的返回地址被"露"在栈顶,此时处理器按照这个返回地址跳到main函数代码区中执行。

在实际运行中,main函数并不是第一个被调用的函数,程序被装入内存前还有一些其他操作,上图只是栈在函数调用过程中所起作用的示意图。

ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。

EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈顶的底部。

函数栈帧:ESP和EBP之间的内存空间为当前栈帧,EBP标识了当前栈帧的底部,ESP标识了当前栈帧的顶部。

EIP:指令寄存器(extended instruction pointer),其内存放着一个指针,该指针永远指向下一条待执行的指令地址。

函数调用大致包括以下步骤:

1.参数入栈:将参数从右向左依次压入系统栈中;

2.返回地址入栈:将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行;

3.代码区跳转:处理器从当前代码区跳转到被调用函数的入口处。

4.栈帧调整:具体包括:

保存当前栈帧状态值,已备后面恢复本栈帧时使用(EBP入栈);

将当前栈帧切换到新栈帧。(将ESP值装入EBP,更新栈帧底部)

给新栈帧分配空间。(把ESP减去所需空间的大小,抬高栈顶)

转自:http://www.cnblogs.com/wsw-seu/p/8278547.html

C/C++函数调用的压栈模型相关推荐

  1. c语言函数调用参数调用的太少,浅谈C语言函数调用参数压栈的相关问题

    参数入栈的顺序 以前在面试中被人问到这样的问题,函数调用的时候,参数入栈的顺序是从左向右,还是从右向左.参数的入栈顺序主要看调用方式,一般来说,__cdecl 和__stdcall 都是参数从右到左入 ...

  2. c语言函数参数压栈,函数调用压栈 浅谈C语言函数调用参数压栈的相关问题

    想了解浅谈C语言函数调用参数压栈的相关问题的相关内容吗,在本文为您仔细讲解函数调用压栈的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:函数调用压栈,下面大家一起来学习吧. 参数入栈的顺序 ...

  3. C++ 函数调用的压栈过程

    调用fun()的过程大致如下: main()======== 参数拷贝(压栈),注意顺序是从右到左,即c-b-a: 保存d = fun(a, b, c)的下一条指令,即cout<<d< ...

  4. 压栈, 跳转,执行,返回:从汇编看函数调用

    From:https://www.jianshu.com/p/594357dff57e C函数调用过程原理及函数栈帧分析:https://blog.csdn.net/zsy2020314/articl ...

  5. 函数调用 压栈的工作原理

     1.开篇 本篇文章着重写的是系统中栈的工作原理,以及函数调用过程中栈帧的产生与释放的过程,有可能名字过大,如果不合适我可以换一个名字,希望大家能够指正,小丁虚心求教!如果有哪里写的不清楚的或者错 ...

  6. 函数在实现过程内存中的压栈和出栈

        关于函数在调用过程中的压栈和出栈问题在学习的时候就感觉很经典,对程序的把握可以提升一个台阶.     一.首先让我们写出一个简单的函数.(我是在vc6.0中实现,并不表示vs编译器底下不可以实 ...

  7. C语言的函数调用过程(栈帧的创建与销毁)

    从汇编的角度解析函数调用过程 看看下面这个简单函数的调用过程: 1 int Add(int x,int y)2 {3 int sum = 0;4 sum = x + y;5 return sum;6 ...

  8. C语言函数参数压栈顺序为何是从右到左?

    #转载自:http://blog.csdn.net/jiange_zh 上学期学习了汇编语言,并在操作系统实验中使用了汇编+C语言混合编程,中间也了解了一些C语言与汇编语言的对应关系. 由于汇编语言是 ...

  9. 汇编中call printf参数压栈时错误理解

    EAX, ECX,EDX,EBX均可以32bit,16bit,8bit访问,如下所示: <-------------------EAX------------------------> | ...

最新文章

  1. IDEA 2020.2 稳定版发布,带来了不少新功能...
  2. 基于Keras搭建cifar10数据集训练预测Pipeline
  3. msmq发送速度的测试
  4. WordPress 图片防盗链的方法
  5. JSP内置 对象(下)
  6. 便携式文件夹加密器 lockdir 5.74
  7. python3 利用Instaloader下载instagram数据示例
  8. JS校验上传图片类型
  9. html小游戏开题报告,html5毕设开题报告
  10. 阿里巴巴大数据实践:大数据建设方法论OneData
  11. excel计算机一级打不开,电脑打不开excel表格是怎么回事呢?
  12. 开启更优网络的时代:Po.et迈入主网
  13. python递归排列组合_Python 排列组合
  14. 【2018年11月12日】其他化学制品行业的股票估值
  15. JDO持久框架——DataNucles
  16. Kotlin编译与Intrinsics检查
  17. Round12—Huffman 树
  18. 华为机试--字符串ASC码+偏移量实现加密
  19. 拉姆达表达式学习(2)
  20. ibm服务器报错代码大全_IBM错误代码对应表

热门文章

  1. 正则表达式(Java版整理)
  2. 容器学习 之 镜像的分层结构(六)
  3. Linux 环境下安装 Golang
  4. lucene的数据类型
  5. Thrall’s Dream HRBUST - 2048【BFS or 强连通分量】
  6. Python数据结构学习笔记——搜索与排序算法
  7. android平板2018,荣耀平板5和ipad2018哪个值得买 荣耀平板5和ipad2018哪个好
  8. php读取移动硬盘数据,移动硬盘打不开,数据怎么恢复?
  9. python爬虫之urllib,伪装,超时设置,异常处理
  10. php检查图片大小,如何利用Javascript函数检查图片大小