有符号数比较时的标志位的计算

目录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 的组合。

理解这一点对 汇编编程、逆向工程、编译器优化 非常重要!