015、指令—加减乘除基础
加法指令
ADD
1 | add destination, source |
ADD 执行普通加法,结果写回目标操作数,并更新 CF、OF、SF、ZF、AF、PF 等状态标志。
1 | mov al, 0FFh |
这里按无符号数解释发生进位,所以 CF = 1;按 8 位有符号数解释,-1 + 1 = 0,没有有符号溢出。
ADC
1 | adc destination, source |
实际计算:
1 | destination = destination + source + CF |
ADC 用于处理超过寄存器宽度的多精度加法。
1 | ; EDX:EAX + ECX:EBX |
低 32 位产生的进位通过 CF 传递给高 32 位。
INC
1 | inc eax |
INC 把操作数加 1。它会影响多数算术标志,但不修改 CF。
因此 INC 不能替代需要传播进位的 ADD。
减法指令
SUB
1 | sub destination, source |
实际计算:
1 | destination = destination - source |
SUB 会更新 CF、OF、SF、ZF、AF、PF。减法中的 CF 可以理解为无符号借位标志。
SBB
1 | sbb destination, source |
实际计算:
1 | destination = destination - source - CF |
它与 ADC 对应,用于多精度减法:
1 | ; EDX:EAX - ECX:EBX |
DEC
DEC 把操作数减 1,与 INC 一样不会修改 CF。
NEG 与补码
1 | neg eax |
NEG 计算 0 - EAX,也就是求二进制补码相反数:
1 | 按位取反 + 1 |
1 | mov eax, 5 |
若源操作数为 0,CF = 0;只要源操作数非 0,CF = 1。对最小有符号数求负会超出表示范围并置 OF。
BCD 调整指令
DAA 与 DAS 用于对压缩 BCD 加减结果做十进制调整,主要依赖 AF 和 CF。
| 指令 | 用途 |
|---|---|
| DAA | 调整加法后的 AL |
| DAS | 调整减法后的 AL |
它们属于历史兼容指令,在 64 位模式下不可用。现代逆向中不常见,但遇到老程序、财务编码或刻意混淆时仍要能识别。
无符号乘法 MUL
单操作数 MUL 使用隐式累加器,结果宽度是操作数宽度的两倍。
| 操作数宽度 | 被乘数 | 结果 |
|---|---|---|
| 8 Bit | AL | AX |
| 16 Bit | AX | DX:AX |
| 32 Bit | EAX | EDX:EAX |
| 64 Bit | RAX | RDX:RAX |
1 | mov eax, 100000h |
如果结果高半部分非零,说明结果无法只放进低半部分,CF 和 OF 会置 1。
有符号乘法 IMUL
IMUL 按有符号数解释操作数,常见三种形式:
1 | imul ecx ; EDX:EAX = EAX * ECX |
双操作数、三操作数形式只保留目标宽度的低位结果。若舍弃的高位不是低位结果的正常符号扩展,CF 和 OF 会置 1。
除法 DIV 与 IDIV
除法也使用隐式被除数和结果寄存器:
| 除数宽度 | 被除数 | 商 | 余数 |
|---|---|---|---|
| 8 Bit | AX | AL | AH |
| 16 Bit | DX:AX | AX | DX |
| 32 Bit | EDX:EAX | EAX | EDX |
| 64 Bit | RDX:RAX | RAX | RDX |
1 | xor edx, edx |
DIV 按无符号数处理;IDIV 按有符号数处理。
除法前的数据扩展
无符号除法常把高半部分清零:
1 | xor edx, edx |
有符号除法需要把低半部分符号扩展到高半部分:
| 指令 | 扩展 |
|---|---|
| CBW | AL -> AX |
| CWD | AX -> DX:AX |
| CDQ | EAX -> EDX:EAX |
| CQO | RAX -> RDX:RAX |
1 | mov eax, -100 |
除法异常
以下情况会触发除法错误异常 #DE:
- 除数为 0;
- 商超出目标寄存器可表示范围。
除法溢出不是通过 CF 或 OF 报告,而是直接触发异常。
标志位速记
| 指令 | 关键点 |
|---|---|
| ADD/SUB | 正常更新算术标志 |
| ADC/SBB | 额外使用 CF 传播进位或借位 |
| INC/DEC | 不修改 CF |
| NEG | 计算补码相反数 |
| MUL/IMUL | 关注隐式结果寄存器与 CF/OF |
| DIV/IDIV | 关注高低寄存器、扩展与 #DE |
学习检查清单
| 检查项 | 状态 |
|---|---|
| 能用 ADC/SBB 完成高低位进位传递 | 待复盘 |
| 记得 INC/DEC 不修改 CF | 待复盘 |
| 能写出 MUL、DIV 的隐式寄存器组合 | 待复盘 |
| 能区分无符号清零与有符号 CDQ 扩展 | 待复盘 |
知道除零与商溢出会触发 #DE |
待复盘 |












