C++函数调用过程中栈区的变化
先简单说一下什么是栈帧
大多数机器的数据传递、局部变量的分配和释放通过操纵程序栈来实现。为单个过程(函数调用)分配的那部分栈称为栈帧。
栈帧 stack frame
定义:机器用栈来自传递过程参数,存储返回信息,保存寄存器为以后恢复及本地存储。
作用:用于控制和保存一个函数调用过程的所有信息的
组成:由两个寄存器组成的 -- 栈指针和帧指针。
- 栈指针%esp是指向栈帧的顶部,是可以移动的。%esp指向低地址
- 帧指针%ebp是指向栈帧的最底部,一般用他来访问栈里的元素。只要栈帧没有消失,帧指针是不会移动的。%ebp指向高地址
注意:栈的地址是从高地址往低地址延伸,函数每一次的调用都有自己独立的栈帧。
栈帧示意图
一般来说,我们将 %esp
到 %ebp
之间区域当做栈帧。并不是整个栈空间只有一个栈帧,每调用一个函数,就会生成一个新的栈帧。
在函数调用过程中,我们需要用栈保存以下数据:
- 调用函数需要知道在哪里获取被调用函数返回的值;
- 被调用函数需要知道传入的参数在哪里,返回的地址在哪里。
- 需要保证在被调用函数返回后,
%ebp
,%esp
等寄存器的值应该和调用前一致。
可以去看看函数的调用示例的汇编代码,这样会更快理解,这里有一些例子
- http://www.cs.virginia.edu/~evans/cs216/guides/x86.html
- https://www.cnblogs.com/clover-toeic/p/3755401.html
函数调用流程
简单的来说就是先将函数压栈,当函数调用结束后,再出栈
普通函数调用流程:
- 开辟栈帧空间
- 函数参数从右至左进行压栈
- 函数返回地址进行压栈
- 函数局部变量进行压栈
虚函数调用流程(大体)
- 查找this指针(也就是实例)的地址
- 根据this指针,查找虚函数表(函数指针数组)的地址
- 从虚函数表中,取出相应的函数地址
- 之后的调用和普通函数调用方式一致
为什么参数从右至左压栈
- 可以动态变化参数个数。通过栈堆分析可知,自左向右的入栈方式,最前面的参数被压在栈底。这样的话,除非知道参数个数,否则是无法通过栈指针的相对位移求得最左边的参数。这样就变成了左边参数的个数不确定,正好和动态参数个数的方向相反。
- 更符合习惯。 采用这种顺序,是为了让程序员在使用C/C++的“函数参数长度可变”这个特性时更方便。
-
- 什么是“函数参数长度可变”?printf就是一个例子,它的参数的个数就是可变的。比如,printf("%d %d %d",1,2,3),在采用从右向左的参数入栈顺序时,参数出栈顺序时"%d %d %d",1,2,3。如果采用从左向右的入栈顺序,则出栈顺序变为3,2,1,"%d %d %d",这样就不能提前知道会有多少个参数
Reference:
- https://www.cnblogs.com/sddai/p/9762968.html
- https://www.cnblogs.com/wiesslibrary/p/15727311.html
__EOF__

本文作者:cancantrbl
本文链接:https://www.cnblogs.com/cancantrbl/p/16037660.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/cancantrbl/p/16037660.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· 单线程的Redis速度为什么快?
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码