x86 汇编 · 溢出检测

OF 溢出标志的硬件检测原理

OF = Carry_In(bit7) XOR Carry_Out(bit7) —— 为什么进出不一致就意味着溢出

01  /  核心问题

OF 关心的只有一件事

运算后,符号位(bit7)还能不能正确反映结果的正负?
符号位的值由三个输入决定:A[7]、B[7]、Carry_In。如果进位的"进"和"出"不一致,就说明符号位被篡改了。
02  /  公式与全加器

bit7 全加器的结构

OF = Carry_In(bit7)
     XOR
     Carry_Out(bit7)
Carry_In:从 bit6 向 bit7 传入的进位
Carry_Out:从 bit7 向更高位溢出的进位(= CF)

bit7 就是一个全加器,三个输入,两个输出:

输入:A[7], B[7], Carry_In(从 bit6 来的进位) 输出:Sum[7](结果的符号位), Carry_Out(向更高位的进位 = CF)
03  /  分类分析

按操作数符号分三大类

第一类:A、B 符号不同(一正一负)

正数加负数,结果绝对值一定变小,永远不可能溢出。

A[7] XOR B[7] = 1(符号不同),无论 Carry_In 是什么,进出始终一致:

A[7] B[7] Carry_In 计算过程 Sum[7] Carry_Out OF = In XOR Out
0 1 0 0+1+0 = 01 1 0 0 XOR 0 = 0 ✔
0 1 1 0+1+1 = 10 0 1 1 XOR 1 = 0 ✔
1 0 0 1+0+0 = 01 1 0 0 XOR 0 = 0 ✔
1 0 1 1+0+1 = 10 0 1 1 XOR 1 = 0 ✔

进位进来一定也出去,或者不进来也不出去——进出始终一致,OF 永远 = 0。


第二类:两个正数相加(A[7]=0,B[7]=0)

Carry_In 计算过程 Sum[7] Carry_Out OF 发生了什么
0 0+0+0 = 00 0 0 0 符号位 = 0(正数),正确 ✔
1 0+0+1 = 01 1 0 1 低位进位把符号从 0 挤成 1,正数变负数 ❌
Carry_In=1 时溢出:低位的进位冲进来,把 0+0 变成了 1,符号位被翻转。但这个进位没有继续输出(Carry_Out=0),说明它被困在了 bit7 里,篡改了符号位。

第三类:两个负数相加(A[7]=1,B[7]=1)

Carry_In 计算过程 Sum[7] Carry_Out OF 发生了什么
0 1+1+0 = 10 0 1 1 两个 1 产生进位,符号清成 0,负数变正数 ❌
1 1+1+1 = 11 1 1 0 进位进来也出去,符号保持 1(负数),正确 ✔
Carry_In=0 时溢出:1+1=10,产生了 Carry_Out,但这个进位不是从低位传来的,而是 bit7 自己产生的。进位凭空出现并带走了符号位的 1,把结果变成了正数。
04  /  完整真值表

所有 8 种组合汇总

A[7] B[7] Carry_In Carry_Out OF = In XOR Out 含义
0 0 0 0 0 两正相加,无溢出
0 0 1 0 1 进位被困,正→负
0 1 0 0 0 一正一负,不可能溢出
0 1 1 1 0 一正一负,不可能溢出
1 0 0 0 0 一负一正,不可能溢出
1 0 1 1 0 一负一正,不可能溢出
1 1 0 1 1 进位凭空产生,负→正
1 1 1 1 0 两负相加,进位穿过,无溢出
规律:全部 8 种组合中,只有 2 种情况 OF=1——恰好对应"两正数加出负数"和"两负数加出正数",这正是有符号溢出的两种情形。Carry_In XOR Carry_Out 能精准区分它们。