有符号数比较时的标志位的计算
目录
在计算机中,有符号数(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的组合。 
理解这一点对 汇编编程、逆向工程、编译器优化 非常重要!
    Do not communicate by sharing memory; instead, share memory by communicating.

                
            
        
浙公网安备 33010602011771号