Skip to content

补码加减运算与溢出判别

2026 大纲 二(二)2 加/减运算:「补码加/减运算器,标志位的生成。」大纲把「标志位的生成」与运算器并列写出,是因为条件转移指令的判断条件全部建立在这四个标志上——不生成标志,加法器就只是一个算数值的部件。

加法器的物理行为,恰好就是补码要求的模运算

补码加减法的三个公式很短:

[A+B]=[A]+[B](mod2n),[AB]=[A]+[B],[B]=[B]+1

真正值得想清楚的是它们为什么不需要额外的硬件配合

🔴 "符号位一起参加运算"和"最高位进位直接丢弃"这两条,其实是同一件事。 一个 n 位加法器天然就是模 2n 的加法器——它只有 n 根输出线,最高位的进位无处可去、自动丢掉,而丢掉的正好是 2n加法器的物理行为恰好就是补码要求的模运算,不是两条要背的规则。

对照一下就知道原码为什么不行:原码的符号位只是一个标签,不带数值权重,送进加法器一起算会得出毫无意义的结果。

🔴 机器里没有独立的减法器。 "末位加 1"也不需要额外做一次加法——加法器最低位本来就有一个进位输入 C0,把它置成 1 就等于免费加了 1。于是 Sub=0 时算 X+YSub=1 时算 X+Y+1=XY一个控制信号、一套加法器、两种运算。

手算求补时有条捷径:从最低位往高位找到第一个 1,该位及其右侧全部不变,左侧全部取反(含符号位)。它与"全部取反加 1"完全等价——加 1 的进位会一路传到第一个 1 为止。

交互可视化

加载可视化中...
加载可视化中...
加载可视化中...

一、加法与减法共用一套加法器

补码的定义本身就是一个模运算:n 位补码把 [2n1, 2n11] 里的每个数映射到 [0, 2n) 里的一个编码,映射规则是「模 2n 同余」。于是

[A+B]=[A]+[B](mod2n)

教材以定点整数按 2n+1 取模、定点小数按 2 取模两种形式给出同一条公式,本质相同,只是小数点约定的位置不同。

减法的问题转成:怎么从 [B] 得到 [B]。因为 X=(2n1)X,所以 X+1=2nXX(mod2n)——取反加一不是口诀,是模 2n 下求相反数的直接算法。落到电路上,一个 n 位加法器只需外挂两样东西就同时具备加、减能力:

器件作用
一排反相器 + 二选一多路器Sub=1 时把 Y 换成 Y 送进加法器
一根从 Sub 接到 C0 的线Sub=1 时最低位进位输入为 1

这就是为什么在任何一张运算器框图里都找不到独立的减法器,也是后面乘法器、除法器里的 ALU「只需支持加和减两种运算」的由来。

二、溢出的两个方向与三种判别方法

溢出指运算结果超出了 n 位补码能表示的范围 [2n1, 2n11],有两个方向:正溢出(结果 >2n11,两正数相加却得到负数)与负溢出(结果 <2n1,两负数相加却得到正数)。

判溢出之前先记住一条能省掉一半工作量的前提:

🔴 只有同号数相加才可能溢出。 异号两数相加,结果的绝对值不会超过较大的那个,必然落在范围内。⚠️ 做减法时"同号"要看实际送进加法器的那两个数(被减数与求补之后的减数)——原式里的异号,到这里已经变成同号了。

三种判别方法常被并列成三条独立规则,其实是同一个判据在电路的不同位置被读出来

  • 符号位比较法V=An1Bn1Sn1+An1Bn1Sn1,读的是三个符号位;
  • 进位判别法OF=Cn1Cn,读的是两个进位;
  • 双符号位法:读的是结果的两位符号位。

硬件更爱进位判别法——一个异或门就够,而且不必等和数产生。

双符号位(变形补码)的读法00 正、无溢出;11 负、无溢出;01 正溢出10 负溢出

🔴 不论是否溢出,高位那个符号位永远是真正的符号。 ⚠️ 另外双符号位不进存储器——正确的数两位符号位必然相同,存两份是浪费;它只在送进加法器时把那一位复制成两位。

🔴 进位丢弃 溢出。 进位丢弃是模 2n 运算的正常行为,每次运算都可能发生,本身不代表任何错误。判溢出必须同时看 Cn1Cn,只看一个 Cn 什么也说明不了。

⚠️ 最后交代下标约定:本站统一 C0 是加法器最低位的进位输入、Cn 是最高位(符号位)的进位输出。有些资料反过来标(把符号位的进位记作 C0,判据写成 V=C0C1),含义相同、只是下标方向相反——两套混用会把判断做反,看图时以图上的标注为准

三种方法为什么恒等:进位判别法与符号位比较法的逐情形推导,以及双符号位法的恒等式(想弄清它们不是三件事、或不放心双符号位法的原理时展开)

进位判别法与符号位比较法为什么等价。 符号位上做的是一次全加:Sn1=An1Bn1Cn1

  • 两数都是正数(An1=Bn1=0):符号位是 0+0+Cn1,必然不产生进位,Cn=0;而 Sn1=Cn1。于是"和为负"Cn1=1Cn1Cn=1
  • 两数都是负数(An1=Bn1=1):符号位是 1+1+Cn1,必然产生进位,Cn=1;而 Sn1=Cn1。于是"和为正"Cn1=0Cn1Cn=1
  • 两数异号:符号位是 1+0+Cn1,进位直接穿过去,Cn=Cn1,异或恒为 0——与"异号不溢出"完全吻合。

双符号位法就是进位判别法的"硬件版"。 把每个操作数扩成两位符号位(正数补 00、负数补 11),两位符号位连同数值位一起参加运算,模数从 2n 变成 2n+1(对小数即从 2 变成 4,故也叫模 4 补码)。把结果的两位符号位记作 S1S0,由于两个操作数的两位符号位相同:

S0=An1Bn1Cn1,S1=An1Bn1Cn

两式异或,An1Bn1 全部抵消:

S1S0=Cn1Cn

"两位符号位不同"与"两个进位不同"是恒等式,不是巧合。 双符号位法所做的,无非是多花一位加法器硬件,把 Cn1Cn 这个异或算成了一位可以直接看的结果——代价是多一位,收益是不必额外引出进位线。在 8 位下穷举全部 65536(A,B) 组合,三种方法与真实溢出情况完全一致。

两组数据上把三种方法各跑一遍(想看"同一个电路的三个读出位置"具体怎么对上,或想确认进位丢弃不等于溢出时展开)

(一)[A]=01100100+100),[B]=00111000+56),8 位。

  01100100  (+100)
+ 00111000  (+56)
----------
  10011100
  • 符号位比较法An1=Bn1=0Sn1=1——同号相加得异号,溢出。
  • 进位判别法:最高数值位向符号位有进位 Cn1=1;符号位 0+0+1 不产生进位,Cn=010=1,溢出。
  • 双符号位法001100100 + 000111000 = 010011100,符号位 01正溢出;高位符号位为 0,说明真正的符号是正。

三条路径读的是同一个电路的三个不同位置。真值 156>127,确实越界。

(二)[A]=1011010175),[B]=1100101153),8 位。

  10110101  (-75)
+ 11001011  (-53)
----------
1 10000000   ← 最高位进位丢弃
  • 符号位比较法:同为负,结果符号位也是 1——无溢出。
  • 进位判别法Cn1=1Cn=111=0,无溢出。
  • 双符号位法110110101 + 111001011 = 110000000(丢弃最高进位),符号位 11,无溢出。

这一组最高位有进位(被丢弃)却没有溢出——进位丢弃与溢出是两件事。结果 10000000 =128,恰好是 8 位补码的下界:补码的负边界能取到 2n1,比正边界的绝对值大 1

三、标志位的生成

n 位运算结果为 FCout 是加法器的进位输出(即 Cn),Cn1 是最高数值位向符号位的进位,Sub 是加/减控制信号(同时接在 C0 上):

标志表达式对谁有意义
ZF(零标志)ZF=1F=0两者都有
SF(符号标志)SF=Fn1只对带符号数
OF(溢出标志)OF=CnCn1只对带符号数
CF(进位/借位标志)CF=SubCout只对无符号数

教材把 CF 写成 CF=CoutCin。因为 Sub 就接在 Cin 上,两式是同一式子。

8 位无符号减法验算 CF 的取反规则:

运算结果CoutCF含义
50H − 30H20H10够减,无借位
30H − 50HE0H01不够减,有借位

🔴 CF 不能直接取 Cout 减法在硬件上是 X+Y+1够减时最高位反而会产生进位;而无符号减法里 CF 的语义是"借位",够减时不该置位。所以加法取 Cout、减法取 Cout,合起来就是 CF=SubCout

🔴 减法的 OF 也必须单独推,不能照抄加法版:

OF=An1Bn1Fn1+An1Bn1Fn1

读作「AB 异号,且差与 A 异号」。把加法版的同号项照搬到减法上,8 位下有一半的输入组合会判错。

🔴 CF 与 OF 可以任意组合,因为它们判的根本不是同一件事:01100100+00111000 得 CF 0 / OF 1;11111111+00000001 得 CF 1 / OF 0;10000000+10000000 得 CF 1 / OF 1。无符号比较用 CF,带符号比较用 OF 和 SF。

四个标志存入标志寄存器 FR,其输出接到控制器 CU 的输入端——条件转移指令就是读这些位来决定跳不跳。例如无符号数的"大于"用 CF+ZF(既没借位、又不相等)。

考点速记

  1. 补码加法能让符号位参与运算、最高位进位直接丢弃,是因为加法器本身就是模 2n 加法器;减法通过 X+Y+1 实现,"末位加 1"由最低位进位输入 C0 免费提供,机器里没有独立的减法器
  2. 只有同号数相加才可能溢出(减法看被减数与求补后的减数);三种判别方法本质相同,由 Sn1=An1Bn1Cn1 与恒等式 S1S0=Cn1Cn 相互推出;进位丢弃 溢出
  3. 四个标志 ZF/SF/OF/CF 中,CF 管无符号、OF 管带符号,同一次运算两者可以取值不同;减法的 CF 要取 Cout 的反,减法的 OF 表达式也必须单独推

这一节在真题里被考过的形式(下方「真题练习」里属于本篇的那几道):

  • 给两个数与一个运算,问会不会溢出:先看送进加法器的那两个数是否同号——异号直接判不溢出,同号再看结果符号有没有反过来。x=103y=25 这类题里,-x-y 才是同号相加的那一个。
  • 给两个补码机器数,问 xy 的值与 OF:按 X+Y+1 实做一遍,用 Cn1Cn 判 OF。⚠️ 别用加法的同号判据去套减法。
  • 给一组数据下的 OF 与 CF,问换一组数据后 OF 与 CF 是多少:这类题考的正是两者互相独立——把新数据实做一遍,分别用各自的判据读出来,不能从旧结果推。
  • 问某条件转移指令的转移条件是什么标志组合:先分清是无符号比较还是带符号比较——无符号用 CF 与 ZF(如"大于"是 CF+ZF),带符号用 SF、OF 与 ZF。这一步分错,四个选项都对不上。

易错:把进位丢弃当成溢出。要同时看 Cn1Cn

易错:做减法时按原式的符号判"同号"。要看求补之后送进加法器的那两个数。

易错:减法直接取 Cout 当 CF。够减时反而有进位,要取反。

易错:用 CF 判带符号溢出、或用 OF 判无符号进位。两者各管一边。

教材出处
  • 一位符号位判溢出、"符号位进位与最高有效位进位异或"判据:唐朔飞《计算机组成原理》第 3 版 §6.2 定点运算,印刷页 p239–p240
  • 变形补码(模 4 补码)定义、"两位符号位不同即溢出、高位符号位永远代表真正的符号"、双符号位只在加法器中展开:同书印刷页 p240–p241
  • 补码加减运算基本公式与"求补"减法:同书印刷页 p237
  • 带标志加法器的四个标志表达式(OF=CnCn1SF=Fn1CF=CoutCin):袁春风《计算机组成与系统结构》第 3 版 §3.2.3 带标志加法器,印刷页 p58
  • 补码加减统一用加法处理、Sub 同时接反相器与最低位进位输入的电路(图 3.9):同书 §3.3.1 补码加减运算,印刷页 p60
  • 四个标志各自对谁有意义、CF=SubCout 的推导、两种溢出判别逻辑表达式并列给出:同书印刷页 p61

相关知识

算术逻辑单元(ALU)定点数编码的转换与书写真值与机器数:四种编码的定义乘除运算的基本原理与实现结构

真题练习