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

一、什么是栈帧(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)

相关推荐
GIS开发特训营3 天前
常见二三维GIS数据分类及处理流程图
学习·流程图·gis·gis开发·webgis
JZC_xiaozhong10 天前
OA 审批流与业务流程引擎区别:企业流程自动化进阶
运维·自动化·流程图·bpm·业务流程管理·流程设计可视化·流程监控
杨筱毅12 天前
【Android】Handler/Looper机制相关的类图和流程图
android·java·流程图
时光追逐者13 天前
一个使用 WPF 开发的 Diagram 画板工具(包含流程图FlowChart,思维导图MindEditor)
c#·.net·wpf·流程图
helloworddm13 天前
Orleans 流系统握手机制流程图
流程图
做科研的周师兄18 天前
【机器学习入门】8.2 主成分分析:一文吃透主成分分析(PCA)—— 从原理到核心逻辑
人工智能·算法·决策树·机器学习·流程图
做科研的周师兄22 天前
【机器学习入门】7.1 决策树 —— 像 “判断流程图” 一样做分类
决策树·机器学习·流程图
东风西巷23 天前
draw.io(免费流程图制作工具) 中文绿色版
学习·电脑·流程图·软件需求·draw.io
aesthetician1 个月前
ReactFlow:构建交互式节点流程图的完全指南
前端·流程图·react
fish-man1 个月前
测试流程图展示问题
linux·服务器·流程图