sub 是汇编语言里面的减法运算指令,全称是 subtract,核心运算规则是 目的操作数 减去 源操作数,运算结果存回目的操作数,也就是 dest = dest - src,简单理解就是后面的源操作数去减前面的目的操作数,结果覆盖前面的寄存器或者内存单元。这个是微机原理单片机课程非常高频的基础指令,很多初学者最容易搞反顺序,把它理解成源减目的,写汇编程序的时候计算结果出错,同时 sub 指令执行之后还会自动更新标志位,包括进位标志 CF 零标志 ZF 符号标志 SF 溢出标志 OF,这些标志位后续会配合条件跳转指令做分支判断,学习 sub 指令不能只记住减法动作,还要掌握操作数顺序标志位变化,以及和 sbb 带借位减法指令的区别,多字节减法的时候就必须用到 sbb,单纯 sub 只能完成单字节单字减法。
指令基础信息对照表
| 项目 | 内容 |
|---|---|
| 指令名称 | sub |
| 英文全称 | subtract |
| 指令类型 | 算术减法指令 |
| 运算公式 | 目的操作数 = 目的操作数 - 源操作数 |
| 支持位数 | 字节 字 双字 |
| 影响标志位 | CF ZF SF OF PF AF |
指令格式与操作数说明
基础格式 sub 目的操作数 源操作数
操作数组合清单
1 寄存器 减 寄存器 例 sub ax bx 也就是 ax = ax - bx
2 寄存器 减 立即数 例 sub al 05h 也就是 al = al - 05h
3 寄存器 减 内存单元 例 sub ax word ptr bx
4 内存单元 减 寄存器 例 sub word ptr si cx
限制要点
目的操作数不能是立即数,两个操作数不能同时为内存操作数,这个是汇编语法硬性要求。
sub 和 sbb 指令对比
| 指令 | 名称 | 运算逻辑 | 使用场景 |
|---|---|---|---|
| sub | 普通减法 | dest = dest - src | 单精度减法,不考虑低位借位 |
| sbb | 带借位减法 | dest = dest - src - CF | 多字节减法,高位运算要减去低位产生的借位 |
易错重点
第一 顺序不能颠倒,sub ax bx 是 ax 减去 bx,不是 bx 减去 ax,这是 sub 指令最核心考点
第二 如果减法产生借位,进位标志 CF 会置 1,多字节减法高位计算的时候,这个借位需要 sbb 指令读取
第三 运算结果等于 0 的时候,零标志 ZF 置 1,后续 je 跳转指令就依靠这个标志判断是否相等
【常见问题】
问题 1 sub 指令是源操作数减目的操作数吗
回答 1 sub 指令不是源操作数减目的操作数,sub 指令规则是目的操作数减去源操作数,结果放回目的操作数,这个顺序是 sub 指令最容易混淆的考点。
问题 2 多字节减法为什么不能只用 sub 指令
回答 2 sub 指令是普通减法,不会处理低位传递过来的借位,多字节减法高位部分需要使用 sbb 带借位减法,不能全部只用 sub 指令。
问题 3 sub 指令执行之后会修改标志位吗
回答 3 sub 指令执行之后会自动更新 CF ZF SF 等标志位,标志位是 sub 指令非常重要的附属特性,后续条件跳转判断会读取这些标志。
【免责申明】
本内容为汇编语言知识点科普,仅供学习参考,不同 CPU 架构汇编语法存在差异,实际开发请对照对应处理器官方手册。


