x86 汇编 · 标志位笔记

有符号数比较与标志位判断

JGE 为何依赖 SF 与 OF,以及 OF=1 时符号翻转的原理

01  /  JGE 的跳转条件

JGE 如何用 SF 和 OF 判断大小

SF = OF
执行 CMP A, B(本质为 A − B)后,
若 SF 与 OF 相等,则认为 A ≥ B,触发跳转。
情况 A − B 结果 SF OF SF = OF? 跳转?
A > B,无溢出 正数 0 0 0 = 0 ✔ 跳转
A = B,无溢出 0 0 0 = 0 ✔ 跳转
A < B,无溢出 负数 1 0 1 ≠ 0 ✘ 不跳
A < B,有溢出 符号被翻转 0 1 0 ≠ 1 ✘ 不跳
A > B,有溢出 符号被翻转 1 1 1 = 1 ✔ 跳转

OF=1 时,为什么 SF=1 且 OF=1 反而意味着 A ≥ B?

OF 的定义:运算结果超出有符号数的表示范围,导致符号位发生了错误翻转。OF=1 时,SF 所呈现的符号一定与真实结果相反。

用具体数字说明(8位有符号数,范围 −128 ~ +127):

A = 100,B = −50,显然 A > B,JGE 应该跳转。真实结果 100 − (−50) = 150,超出 +127,发生正溢出:

; A = 100 = 0110 0100
; B = −50,取反加1 = 0011 0010
 
0110 0100
+ 0011 0010
───────────
1001 0110 ← 被截断为 −106(有符号解读)
 
; SF = 1(最高位是1,看起来像负数)← 这是假象
; OF = 1(真实结果150超出范围,溢出)
SF=1 是假象:真实结果是 +150(正数),但进位把符号位从 0 压成了 1。SF 告诉你"负数",但实际是正数。OF=1 正是在告诉你"SF 的符号是错的,要取反才是真相"。
溢出方向 真实结果 SF(假象) OF 真实符号 = SF XOR OF
正溢出(结果 > +127) 正数 1(错) 1 1 XOR 1 = 0 → 正 ✔
负溢出(结果 < −128) 负数 0(错) 1 0 XOR 1 = 1 → 负 ✔
核心公式

真实符号 = SF XOR OF

JGE 跳转条件 = 真实结果 ≥ 0 = (SF XOR OF) = 0 = SF = OF

SF 是"加了噪声的符号",OF 就是那个噪声。SF XOR OF 把噪声消掉,还原真实符号。SF=1 且 OF=1,两个 1 异或得 0,说明真实结果是正数,A ≥ B,所以跳转。

02  /  为什么不用 CF

CF 是为无符号数设计的

CF 的定义:记录运算时最高位是否产生了借位或进位。对无符号数,借位能正确反映大小关系。但 CF 完全看不懂符号位,它把所有数都当作无符号的位模式处理。
反例:CF 在有符号数中给出错误结论(8 位)
A B 实际大小 CF CF 的结论 正确?
−1 1 −1 < 1 0 CF=0 → 误判为 A ≥ B ❌ 错误
127 −1 127 > −1 1 CF=1 → 误判为 A < B ❌ 错误
根本原因:CF 只记录二进制借位,不知道数有没有符号。有符号数必须用 SF 和 OF 配合,才能还原真实的大小关系。
有符号数

使用 SF / OF

  • 大于等于 JGE  SF=OF
  • 大于 JG   SF=OF, ZF=0
  • 小于等于 JLE  SF≠OF 或 ZF=1
  • 小于 JL   SF≠OF
无符号数

使用 CF

  • 大于等于 JAE  CF=0
  • 大于 JA   CF=0, ZF=0
  • 小于等于 JBE  CF=1 或 ZF=1
  • 小于 JB   CF=1
一句话总结

CF 只记录"二进制借位",对有符号数毫无意义,会给出错误结论。

SF + OF 的配合能正确反映有符号运算后的真实正负关系——OF 像一个"纠错位",在发生溢出时翻转判断逻辑,使 SF 的含义始终可信。