关于 栈帧变化完整流程图(函数嵌套)

一、什么是栈帧(Stack Frame)

当一个函数被调用时,会在栈上开辟一段空间,叫做 栈帧

每个栈帧保存了:

  • 函数的参数

  • 返回地址(从哪里跳回来)

  • 上一个栈帧的栈底指针(保存调用者的 EBP / FP)

  • 局部变量

  • 保存的一些寄存器(可选)


二、函数嵌套调用例子

以 C 为例:

cpp 复制代码
void C() {
    int c = 3;
}

void B() {
    int b = 2;
    C();
}

void A() {
    int a = 1;
    B();
}

int main() {
    A();
    return 0;
}

三、每次函数调用的栈帧结构(以 x86 为例)

栈增长方向:从高地址向低地址

每次调用栈帧大致如下(从下到上):

bash 复制代码
高地址
│
│  上一帧的 EBP(caller 的栈底)
│  返回地址(RET)
│  参数(如有)
│  局部变量(如 int x)
│
↓
低地址

四、函数嵌套时完整栈帧流程图

以调用链**main → A → B → C** 为例,假设每层函数内部有 1 个**int** 局部变量。

bash 复制代码
初始状态:
栈空

main() 被调用:
+-------------------+ ← ESP,EBP(main 的栈底)
| 返回地址          |
+-------------------+
| 局部变量 return=0 |
+-------------------+

main() → A()
+-------------------+ ← ESP(当前)
| 返回地址(main)    |
+-------------------+
| 上一帧的 EBP      |
+-------------------+
| 局部变量 a=1      |
+-------------------+

A() → B()
+-------------------+
| 返回地址(A)       |
+-------------------+
| 上一帧的 EBP      |
+-------------------+
| 局部变量 b=2      |
+-------------------+

B() → C()
+-------------------+
| 返回地址(B)       |
+-------------------+
| 上一帧的 EBP      |
+-------------------+
| 局部变量 c=3      |
+-------------------+

栈顶 (ESP)

五、函数返回时的栈帧回退过程

函数返回时,会弹出当前栈帧,恢复上一个函数的栈帧(EBP 和 RET 地址)。

bash 复制代码
C() return → ESP 恢复到 B()
B() return → ESP 恢复到 A()
A() return → ESP 恢复到 main()
main() return → 程序结束

六、流程图总结

bash 复制代码
main
│
├── 调用 A()
│   │
│   └── 调用 B()
│       │
│       └── 调用 C()
│
└── 每层函数进栈,栈帧不断叠加
    每层函数返回,栈帧依次弹出

七、可视化理解

bash 复制代码
栈顶
│
│  C 的局部变量
│  返回地址(B)
│
│  B 的局部变量
│  返回地址(A)
│
│  A 的局部变量
│  返回地址(main)
│
│  main 的局部变量
│  返回地址(操作系统)
↓
栈底

八、汇编视角分析

以 x86 为例,函数调用时常见的指令:

Clojure 复制代码
CALL func   ; 压入返回地址 → 跳转
PUSH EBP    ; 保存当前帧
MOV EBP, ESP; 建立新栈帧
SUB ESP, n  ; 为局部变量分配空间
...
MOV ESP, EBP; 恢复 ESP
POP EBP     ; 恢复上层栈帧
RET         ; 弹出返回地址

九、总结

步骤 栈帧变化 关键指令
函数调用 新栈帧入栈 CALLPUSH EBP
建立栈帧 保存旧帧 & 分配空间 MOV EBP, ESPSUB ESP, n
函数返回 弹出栈帧 MOV ESP, EBPPOP EBPRE

补充:

  • 在 x86_64 下,函数参数会用寄存器传递(如 RDI、RSI)

  • 在 ARM64 下,栈帧也有 FP/LR(Frame Pointer / Link Register)结构

  • 调用链跟踪调试可用 gdb、ida、ghidra 中的栈回溯(backtrace)

相关推荐
数据爬坡ing6 天前
软件工程总体设计:从抽象到具体的系统构建之道
数据库·流程图·软件工程·可用性测试·软件需求
zzywxc7876 天前
深入解析大模型落地的四大核心技术:微调、提示词工程、多模态应用 及 企业级解决方案,结合代码示例、流程图、Prompt案例及技术图表,提供可落地的实践指南。
人工智能·深度学习·机器学习·数据挖掘·prompt·流程图·editplus
sjzmj68139 天前
脑洞大开——AI流程图如何改变思维?
人工智能·信息可视化·流程图·数据可视化
风口的程序猿10 天前
Vue自定义流程图式菜单解决方案
流程图·vue-router优化·显式业务流程管理·vue菜单优化·流程式菜单
wcy011212 天前
vue3+vue-flow制作简单可拖拽可增删改流程图
javascript·vue.js·流程图
zzywxc78712 天前
深入探讨AI在测试领域的三大核心应用:自动化测试框架、智能缺陷检测和A/B测试优化,并通过代码示例、流程图和图表详细解析其实现原理和应用场景。
运维·人工智能·低代码·架构·自动化·流程图·ai编程
hetongqiyue14 天前
orbslam2 localMapping流程图
流程图
c_zyer16 天前
Mermaid流程图可视化系统:基于Spring Boot与Node.js的三层架构实现
spring boot·node.js·流程图·mermaid
范纹杉想快点毕业16 天前
基于 C 语言视角:流程图中分支与循环结构的深度解析
c语言·stm32·单片机·设计模式·架构·流程图·uml
火车叨位去194922 天前
用Java实现rpc的逻辑和流程图和核心技术与难点分析
java·rpc·流程图