要准确判断两个带符号整数的大小关系,CPU必须同时参考符号标志位(SF)和溢出标志位(OF),而不能仅仅依赖符号标志位(SF)。

一、带符号整数比较原理详解

计算机中的比较操作通常由一条减法指令来实现,例如CMP A, B指令,其在硬件层面的实际操作是计算 A−B ,但结果不回存,只根据计算结果设置相应的标志位。后续的条件转移指令(如jg, jl等)则根据这些标志位来判断是否跳转。

1. 为什么不能只看SF标志位?

一个常见的误区是:既然SF(Sign Flag)标志位表示结果的符号(SF=1为负,SF=0为正),那么比较 A 和 B 的大小,不就是看 A−B 的结果是正是负吗?

这种想法在不发生溢出的情况下是正确的。但一旦发生算术溢出,结果的符号位就会变得不可靠,甚至与真实结果的符号完全相反。

溢出(Overflow):当两个同号的数相加(或两个异号的数相减)后,结果超出了机器数所能表示的范围。在带符号数运算中,溢出会导致结果的符号位不正确。

溢出标志位(OF) 就是用来检测这种情况的。当运算结果发生溢出时,OF=1,否则OF=0

2. SF与OF的协同工作

为了正确判断带符号数的大小,必须将SF和OF结合起来。我们来分析 jg (Jump if Greater) 和 jl (Jump if Less) 的转移条件。

前提CMP A, B 执行 A−B 操作。我们期望判断 A 是否大于/小于 B。

A > B (对应指令 jg, jnle)

A < B (对应指令 jl, jnge)

二、图示

为了方便记忆,可以将带符号数比较的逻辑总结为下表:
image-4.png

逻辑条件 运算 (A−B) OF SF 转移条件 是否满足
A > B 不溢出,结果为正 0 0 SF=OF
A > B 正溢出,“正-负”,结果看似为负 1 1 SF=OF
A < B 不溢出,结果为负 0 1 SF=OF
A < B 负溢出,“负-正”,结果看似为正 1 0 SF=OF

而对于 jge (大于等于) 和 jle (小于等于),逻辑是类似的,只是放宽了对 ZF 的要求:

三、常考点

  1. 混淆无符号数与有符号数跳转:这是最核心的考点。考生必须清晰地辨别指令助记符。

    • 无符号数ja (above), jb (below)。依据:CFZF

    • 有符号数jg (greater), jl (less)。依据:SF, OFZF

    • je (equal), jne (not equal) 对两者通用,只看 ZF

  2. 忽略CMP指令:条件转移指令本身不进行比较,它只检查标志位。题目中一定会有一个先行指令(如CMP, SUB, ADD等)来设置标志位,分析时必须以该指令的执行结果为依据。

  3. 对溢出判断不熟练:考题常常会精心设计操作数,使其运算结果恰好在溢出的边界上。考生必须熟练掌握溢出的判断方法:

    • 方法一(双符号位法):使用补码的变形,用两个符号位表示。如果运算结果的两个符号位不同(01或10),则表示发生溢出。

    • 方法二(单符号位法):OF=Cs​⊕Cs−1​,即符号位的进位和最高数值位的进位是否不同。对于减法 A−B,等效于计算 A+[B]补​,此时 OF 是判断两个正数相加是否得到负数,或两个负数相加是否得到正数。