005、流程控制语句的识别
先画基本块,再猜语法
基本块是一段单入口、单出口的连续指令。控制流图以基本块为节点、跳转关系为边。
反汇编中真正存在的是比较和跳转;if、switch、for 是对控制流的高级解释。
单分支 if
1 | if (x > 10) |
常见形态:条件不成立时跳过主体。
1 | cmp eax, 10 |
编译器也可能反转条件,因此不要把某一个跳转助记符机械翻译成源码条件。
if-else
1 | 条件 |
其中一个分支末尾通常需要无条件跳转,避免继续落入另一分支。
多条件与判定树
连续的 if/else if 可能表现为线性比较,也可能被优化成更平衡的判定树。恢复时应先列出每条边的条件,再组合成高级逻辑。
switch 的几种实现
线性比较
适用于 case 少、值稀疏的情况。
二分判定树
适用于值较多但分布稀疏的情况。
跳转表
适用于 case 较密集的情况:
1 | sub eax, min_case |
跳转表恢复步骤:
- 找到归一化后的索引。
- 确定边界检查和默认分支。
- 读取表项并标记所有目标。
- 处理多个 case 指向同一目标的情况。
循环识别
while
先判断条件,再执行循环体,可能一次都不执行。
do-while
先执行循环体,尾部再判断,至少执行一次。
for
通常包含初始化、条件、循环体和迭代四部分,但优化后与 while 很难严格区分。
1 | 初始化 → 条件 ─失败→ 退出 |
break 与 continue
break指向循环出口。continue指向下一轮判定或for的迭代部分。
嵌套循环中,必须根据跳转目标属于哪一层循环判断。
循环优化
Release 代码可能出现:
- 循环展开。
- 向量化。
- 强度削弱。
- 循环合并或拆分。
- 不变量外提。
- 已知次数循环被直接展开或计算掉。
优化会让“一个回边对应一个循环”的简单判断失效。需要结合支配关系、数据变化和退出条件观察。
结构化恢复方法
- 标记所有基本块和跳转边。
- 从函数出口向前找汇合点。
- 识别回边和循环头。
- 把复杂条件拆成原子比较。
- 先写
goto版伪代码,再整理成 if/loop。
学习检查清单
| 检查项 | 状态 |
|---|---|
| 能划分基本块并画出控制流图 | 待复盘 |
| 能识别 if 与 if-else 的汇合点 | 待复盘 |
| 能恢复跳转表的索引和范围 | 待复盘 |
| 能区分循环入口判断与尾部判断 | 待复盘 |
| 能识别 break、continue 的跳转目标 | 待复盘 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ruiqy~!





















