栈是什么?
栈(Stack)是一种 后进先出(LIFO) 的数据结构。在汇编中,它由 SS:SP 指向。
PUSH 与 POP
1
2
| PUSH AX ; SP = SP - 2, [SS:SP] = AX
POP BX ; BX = [SS:SP], SP = SP + 2
|
- PUSH:先将 SP 减 2,再写入数据
- POP:先读取数据,再将 SP 加 2
栈帧结构
函数调用时,栈中会形成栈帧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| 高地址
+----------------+
| 参数 2 |
+----------------+
| 参数 1 |
+----------------+
| 返回地址 | ← CALL 自动压入
+----------------+
| 旧 BP | ← PUSH BP
+----------------+ ← BP (当前栈帧基址)
| 局部变量 1 |
+----------------+
| 局部变量 2 |
+----------------+ ← SP (栈顶)
低地址
|
函数调用流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| ; 调用者
PUSH 参数 2
PUSH 参数 1
CALL FUNC
; 被调用者 FUNC:
PUSH BP ; 保存旧栈帧
MOV BP, SP ; 设置新栈帧
SUB SP, 4 ; 分配局部变量空间
; ... 函数体 ...
MOV SP, BP ; 恢复 SP
POP BP ; 恢复旧栈帧
RET ; 弹出返回地址并跳转
|
为什么需要栈?
- 保存返回地址:
CALL 自动将下一条指令地址压栈 - 传递参数:通过栈传递,避免寄存器不够用
- 保存上下文:子程序可以随意使用寄存器,退出前恢复
- 局部变量:每个函数有独立的栈帧,互不干扰
总结
理解栈,就理解了程序执行的"时间线"。每一次函数调用,都是在栈上翻开新的一页。
下一篇:《标志位详解:CF/ZF/SF/OF 如何影响程序流程》