目录1. 关键标志位2. 有符号数比较规则3. 示例分析例 1:5 - 10(正常情况)例 2:127 - (-1)(溢出情况)4. 高级语言中的有符号比较5. 其他架构(ARM/MIPS)6. 总结
在计算机中,有符号数(Signed Number)的比较 依赖于 标志寄存器(FLAGS) 中的多个状态位,包括 符号标志(SF)、溢出标志(OF)、零标志(ZF) 等。与无符号数比较(主要依赖 CF)不同,有符号数的比较需要结合 SF 和 OF 来判断大小关系。
1. 关键标志位
有符号数比较主要依赖以下标志位(以 x86 为例):
标志位
名称
作用
SF(Sign Flag)
符号标志
运算结果的最高位(符号位)为 1 时 SF=1(表示负数)。
OF(Overflow Flag)
溢出标志
运算结果超出有符号数表示范围时 OF=1(如 127 + 1 = -128)。
ZF(Zero Flag)
零标志
运算结果为 0 时 ZF=1(表示相等)。
2. 有符号数比较规则
当执行 CMP A, B(计算 A - B)时,CPU 会根据 SF、OF 和 ZF 来判断 A 和 B 的关系:
比较关系
条件(标志位组合)
解释
A == B
ZF = 1
A - B = 0
A < B
SF ≠ OF
A - B 为负且无溢出 或 正但溢出(实际为负)
A > B
SF == OF && ZF = 0
A - B 为正且无溢出 或 负但溢出(实际为正)
关键点:SF 和 OF 的异或(SF ^ OF)决定 A < B 是否成立。
3. 示例分析
例 1:5 - 10(正常情况)
MOV AL, 5 ; AL = 5 (00000101)
MOV BL, 10 ; BL = 10 (00001010)
CMP AL, BL ; 计算 5 - 10
5 - 10 = -5(二进制补码:11111011)
SF = 1(最高位 1,表示负数)
OF = 0(无溢出)
ZF = 0(非零)
判断:
SF ≠ OF(1 ≠ 0)→ 5 < 10
例 2:127 - (-1)(溢出情况)
MOV AL, 127 ; AL = 127 (01111111)
MOV BL, -1 ; BL = -1 (11111111)
CMP AL, BL ; 计算 127 - (-1) = 128(但 8 位有符号范围是 -128~127)
127 - (-1) = 128(二进制补码:10000000,即 -128)
SF = 1(10000000 是负数)
OF = 1(127 - (-1) 超出 127,溢出)
ZF = 0(非零)
判断:
SF == OF(1 == 1)→ 127 > -1(虽然 SF=1,但溢出导致实际结果应为正)
4. 高级语言中的有符号比较
在 C/C++ 中,有符号比较会被编译为 CMP + 条件跳转:
int a = 5, b = 10;
if (a < b) { // 编译为 `CMP + JL (Jump if Less, SF≠OF)`
// 执行
}
JL(Jump if Less):检查 SF ≠ OF(有符号小于)。
JGE(Jump if Greater or Equal):检查 SF == OF(有符号大于或等于)。
5. 其他架构(ARM/MIPS)
ARM:
使用 CMP 指令,并检查 CPSR 的 N(Negative, 类似 SF)和 V(Overflow, 类似 OF)。
条件码 LT(Less Than)对应 N ≠ V。
MIPS:
使用 SLT(Set Less Than)指令直接计算有符号比较结果。
6. 总结
比较关系
x86 标志位条件
典型跳转指令
A == B
ZF = 1
JE / JZ
A < B
SF ≠ OF
JL
A > B
SF == OF && ZF = 0
JG
关键区别:
无符号比较:依赖 CF(借位)。
有符号比较:依赖 SF 和 OF 的组合。
理解这一点对 汇编编程、逆向工程、编译器优化 非常重要!