首页/计算机组成原理/04-instruction/过程调用的机器级表示 🔗 在 Obsidian 中打开
计算机组成原理 · 04-instruction

过程调用的机器级表示

重要度 ⭐⭐⭐⭐⭐指令系统过程调用函数调用调用约定栈帧
速查
过程调用的核心是栈帧CALL = 压返回地址 + 跳转,RET = 弹返回地址到 PC;帧指针 FP/EBP 固定不动,参数用 FP+偏移、局部变量用 FP−偏移 访问。

速查

项目
对应高级语言函数调用 / 过程调用
核心机制栈帧(Stack Frame)管理
关键指令CALL(调用)和 RET(返回)
调用步骤传参 → 保存返回地址 → 跳转 → 建立栈帧 → 执行 → 恢复 → 返回

核心概念

过程调用(函数调用)在机器级通过栈帧机制实现。每次调用在栈上分配一个栈帧,用于存储局部变量、参数、返回地址和保存的寄存器。

调用过程的完整步骤

  1. 传递参数:将实参按调用约定放入寄存器或压入栈中
  2. 保存返回地址CALL 指令自动将下一条指令地址(返回地址)压栈
  3. 跳转到被调过程:PC 设置为被调过程的入口地址
  4. 建立栈帧:保存旧的帧指针(push ebp),设置新的帧指针(mov ebp, esp),分配局部变量空间(sub esp, N
  5. 执行过程体
  6. 恢复栈帧:释放局部变量空间,恢复旧的帧指针
  7. 返回RET 指令从栈中弹出返回地址到 PC

栈帧结构(从高地址到低地址)

[参数2]        ← ebp + 12
[参数1]        ← ebp + 8
[返回地址]     ← ebp + 4
[旧的ebp]      ← ebp (帧指针)
[局部变量1]    ← ebp - 4
[局部变量2]    ← ebp - 8
[保存的寄存器]  ← esp (栈指针)
记忆锚点ebp 为分界线:正偏移取参数负偏移取局部变量;返回地址永远紧贴在旧 ebp 的高地址侧(ebp+4)。

关键性质

组件作用说明
PC(程序计数器)存储下一条指令地址CALL 修改 PC 为被调过程地址
SP(栈指针)指向栈顶压栈时 SP 减小,弹栈时 SP 增大
FP/BP(帧指针)指向当前栈帧的基址用于访问局部变量和参数
CALL 指令压入返回地址 + 跳转等价于 PUSH 返回地址 + JMP 目标
RET 指令弹出返回地址 + 跳转等价于 POP PC
调用约定参数传递栈清理
cdecl(C 默认)参数从右到左压栈调用者清理
stdcall(Win API)参数从右到左压栈被调者清理
寄存器传参前几个参数放寄存器

常见考法

考法解题套路
分析栈帧布局画出栈帧结构图,标出各部分的地址偏移
CALL/RET 的等价操作$CALL = $ push 返回地址 $+$ JMP;$RET = $ pop PC
给定汇编还原函数调用CALLRET,识别参数传递和返回值
栈的增长方向x86 中栈向低地址增长(push 使 SP 减小)
调用嵌套的栈状态逐层画出栈帧的压入过程

易错点

⚠️ 高频陷阱
  • CALL 不仅是跳转:CALL 会先将返回地址压栈,再跳转。单纯的 JMP 不压栈。
  • 栈向低地址增长:push 操作使 SP 减小,不是增大。
  • 帧指针 FP 的作用:局部变量通过 FP−偏移访问,参数通过 FP+偏移访问。FP 在过程执行期间不变,而 SP 可能变化。
  • 返回值的存放位置:x86 中整数返回值通常放在 EAX/RAX 寄存器中,不在栈上。
  • 被调者需要保存哪些寄存器:callee-saved 寄存器(如 ebx, esi, edi, ebp)由被调过程保存;caller-saved 寄存器(如 eax, ecx, edx)由调用者保存。

核心结论

必背
  1. 过程调用的核心机制是栈帧:每次调用在栈上分配独立的栈帧。
  2. CALL = 压入返回地址 + 跳转;RET = 弹出返回地址 + 跳转。
  3. 栈帧中包含:参数、返回地址、旧帧指针、局部变量、保存的寄存器。
  4. 帧指针 FP 在过程执行期间不变,便于访问参数(FP+偏移)和局部变量(FP−偏移)。
  5. x86 中栈向低地址增长,返回值通过 EAX 传递。

记忆卡片

CALL 指令等价于什么?
push 返回地址 + jmp 目标地址。
RET 指令等价于什么?
pop PC(弹出返回地址跳转)。
栈向哪个方向增长?
低地址方向(push 使 SP 减小)。
局部变量如何访问?
通过帧指针 FP 减偏移。
返回值放在哪里?
EAX/RAX 寄存器。
帧指针 FP 的作用?
固定引用点,方便访问参数和局部变量。

交互动画 · 栈帧的建立与销毁

↑ 高地址 ↓ 低地址(栈向下增长) 参数 2ebp+12 参数 1ebp+8 返回地址ebp+4 旧的 ebpebp 局部变量 1ebp-4 局部变量 2ebp-8 保存的寄存器ebp-12 EBP ▸ ◂ ESP
点击「播放」或「下一步」逐步观察栈帧生长
当前指令:—
示意图:绿色 EBP 固定于栈帧基址不动,橙色 ESP 随压栈/弹栈上下移动;高亮槽表示本步新写入的内容。

相关知识点

selection-machine-level loop-machine-level

↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。