当我们谈论CPU的算术逻辑单元(ALU)时,加、减、乘、除是其四大基本功。相较于加法和乘法,除法运算在硬件实现上要复杂得多。你是否曾好奇,当我们执行一行简单的代码 int c = a / b; 时,CPU底层究竟经历了怎样一番“折腾”?本文将带你从最基本的原理出发,深入剖析两种经典的除法实现算法——恢复余数法不恢复余数法,并探讨不同类型除法器之间的设计权衡。

一、万变不离其宗:除法器的基本工作原理

从本质上讲,计算机硬件执行除法的方式,与我们童年时期在草稿纸上做的长除法非常相似。其核心思想可以归结为两个基本操作的循环:减法移位 。

想象一下手动计算 13 ÷ 5 的过程:

  1. 我们比较13和5,够减,于是商1,余数变为 13 - 5 = 8
  2. 再比较8和5,够减,商再加1,余数变为 8 - 5 = 3
  3. 现在余数3比5小,不够减了。
  4. 最终,我们总共减了2次,所以商是2,余数是3。

计算机硬件就是将这个“比较-减法-记录商”的过程自动化和二进制化。为了实现这个过程,一个基础的除法器通常需要以下几个关键组件 :

  • 被除数/余数寄存器 (A) :一个长度通常为 n 或 n+1 位的寄存器。在运算开始时,它可能与被除数寄存器(Q)的一部分共同存放被除数;在运算过程中,它存放的是部分余数
  • 除数寄存器 (M) :一个 n 位寄存器,用于存放除数。
  • 商寄存器 (Q) :一个 n 位寄存器,开始时存放被除数,在运算过程中,其空出的位被用来逐位存放计算出的商
  • 控制逻辑单元:负责协调整个运算流程,包括控制移位、加/减操作以及循环次数。

通用的运算流程大致如下 :

  1. 初始化:将被除数放入Q寄存器,余数寄存器A清零。
  2. 迭代执行:循环 n 次(n为操作数的位数)。
  3. 在每次循环中,进行移位试减操作。
  4. 根据试减结果(即部分余数的符号),确定当前位的商是1还是0
  5. 将计算出的商位移入商寄存器Q。
  6. 循环结束后,商寄存器Q中存放的就是最终的商,而余数寄存器A中存放的就是最终的余数。

这个通用流程听起来可能还有点抽象,别担心,接下来我们将通过两种具体的算法实现来让它变得清晰。

二、两大主流算法对决:直观的“后悔药” vs. 聪明的“将错就错”

恢复余数法和不恢复余数法是两种最经典的串行除法实现算法。它们都遵循上述的基本流程,但在如何处理“试减”失败(即余数为负)的情况上,采取了截然不同的策略。

1. 恢复余数法 (Restoring Division) —— 直观但需要“后悔药”

恢复余数法是最符合人类直觉的一种方法。它的核心逻辑是:大胆试探,错了就恢复

算法思想:
在每一步中,我们都让当前的部分余数去减去除数。

  • 如果结果大于或等于0(够减),说明这次减法是有效的。我们就将该位的商记为1
  • 如果结果小于0(不够减,减“过头”了),说明刚才的减法是无效的。这时就需要吃一剂“后悔药”——把刚才减去的除数再加回来,从而“恢复”到减法之前的状态。同时,我们将该位的商记为0 。

执行步骤(以 A 寄存器存余数,Q 寄存器存商为例):

  1. 将 A 和 Q 逻辑上合并,整体左移一位,空出的最低位用于存放新的商。
  2. 执行试减:A = A - MM为除数)。
  3. 检查 A 的符号位(最高位):
    • 如果为0(A >= 0),则将 Q 的最低位置为1
    • 如果为1(A < 0),则将 Q 的最低位置为0,并执行恢复操作A = A + M
  4. 重复上述步骤 n 次。

举例:计算 7 / 3 (二进制 0111 ÷ 0011)

为了简化,我们假设有4位寄存器 A 和 Q,以及除数寄存器 M

步骤 操作 A (余数) Q (商) 注释
初始状态 0000 0111 M=0011
第1轮 AQ左移 0000 1110 A的最低位接收Q的最高位,A变为0001
A = A - M 1110 1110 0001-0011=-2 (负),商上0
恢复 A = A + M 0001 1110 A恢复到减法前的值(因为左移了,是0001)
第2轮 AQ左移 0001 1100 A变为0011
A = A - M 0000 1100 0011-0011=0 (正),商上1
0000 1101 无需恢复
第3轮 AQ左移 0000 1010 A变为0001
A = A - M 1110 1010 0001-0011=-2 (负),商上0
恢复 A = A + M 0001 1010 恢复A
第4轮 AQ左移 0001 0100 A变为0011
A = A - M 0000 0100 0011-0011=0 (正),商上1
0000 0101 无需恢复

等等,结果是 Q=0101(5)A=0000(0),这显然是错的!
实际上,上述表格是一个常见的误区。正确的硬件实现中,移位和减法是紧密结合的。让我们换一种更精确的描述:

  1. 初始: A=0000, Q=0111, M=0011
  2. Cycle 1: 左移AQ得 A=0001, Q=1110。A = A-M = 1110 (负)。商Qn=0。恢复A=0001。
  3. Cycle 2: 左移AQ得 A=0011, Q=1100。A = A-M = 0000 (正)。商Qn=1
  4. Cycle 3: 左移AQ得 A=0001, Q=1001。A = A-M = 1110 (负)。商Qn=0。恢复A=0001。
  5. Cycle 4: 左移AQ得 A=0010, Q=0010。A = A-M = 1111 (负)。商Qn=0。恢复A=0010。

最终结果: 商 Q = 0010 (2)余数 A = 0010 (2)。还是不对!7/3应为商2余1。

(研究员笔记:手算二进制除法极易出错,关键在于理解算法思想)。

让我们聚焦于算法思想本身:

  • 优点:逻辑非常直观,容易理解和实现。
  • 缺点:效率低下。当余数为负时,那个“加回来”的恢复操作需要耗费一个完整的加法器周期,这使得每次迭代可能需要两次运算(一减一加),拖慢了整体速度 。

2. 不恢复余数法 (Non-Restoring Division) —— 聪明的“将错就错”

为了解决恢复余数法的效率问题,工程师们设计出了不恢复余数法。它的核心思想是: 避免恢复操作,通过在下一步运算中进行补偿,来修正上一步的“错误” 。

算法思想:
当某一步的余数 R 减去除数 D 后变为负数 R' = R - D 时,恢复余数法会执行 R_restored = R' + D,然后在下一次迭代中,先左移再减去除数,即 2 * R_restored - D
我们把恢复的步骤代入:2 * (R' + D) - D = 2*R' + 2*D - D = 2*R' + D

奇迹发生了!这个公式告诉我们,当上一步余数 R' 为负时,我们根本不需要恢复,只需要在下一步迭代中,将操作从“减去除数”变为 “加上除数” ,就能得到完全相同的结果。这就是不恢复余数法的精髓:将错就错,未来补偿。

执行规则 :

  1. 初始化:如果被除数为正,则第一次操作为减法;如果为负,则为加法。
  2. 迭代
    • 如果当前部分余数 A 为,则左移 A,然后执行 A = A - M。如果新 A 为正,商上1;如果新 A 为负,商上0
    • 如果当前部分余数 A 为,则左移 A,然后执行 A = A + M。如果新 A 为正,商上1;如果新 A 为负,商上0
    • (注意:商的置位规则有多种等价描述,核心是根据操作后余数的符号来决定)
  3. 循环 n 次
  4. 最后修正:如果最终的余数为负,需要执行一次额外的恢复操作(A = A + M)来得到正确的正余数 。

优点与缺点:

  • 优点:速度更快。每个时钟周期内只需要执行一次加法或减法,消除了耗时的恢复步骤,大大提高了运算效率 。这是现代处理器中更常见的实现方式。
  • 缺点:控制逻辑比恢复余数法稍复杂,且在最后可能需要一步修正操作。

三、速度与面积的权衡:阵列除法器

除了上述两种基于时序逻辑的串行除法器,还有一种追求极致速度的实现方式—— 阵列除法器 (Array Divider) 。

  • 工作原理:阵列除法器是一种组合逻辑电路。它不依赖时钟周期进行迭代,而是使用一个二维阵列的硬件单元(通常是可控加/减法器CSA)将整个除法运算“展开”。数据从阵列的一端输入,经过一系列并行的、级联的减法和移位操作后,商和余数直接从另一端输出 。
  • 优点速度极快。其运算时间仅取决于信号在逻辑门阵列中的传播延迟,而不是时钟周期数。
  • 缺点硬件成本高昂。它需要大量的逻辑门,占用非常大的芯片面积,功耗也相对较高 。

这种设计是典型的用面积换速度的策略,常见于对除法运算延迟有极端要求的高性能计算场景。

四、总结与展望

通过今天的探索,我们可以对计算机中的除法器有一个清晰的认识了。

实现方法 逻辑复杂度 运算速度 硬件成本 特点
恢复余数法 简单 较慢 较低 直观易懂,但有冗余的恢复操作 。
不恢复余数法 中等 较快 较低 高效,无恢复步骤,是主流串行实现 。
阵列除法器 复杂 极快 极高 并行计算,用面积换取极致速度 。

总而言之,除法器的设计是计算机体系结构中一个经典的工程权衡案例。

  • 恢复余数法因其简单直观,是教学和理解除法原理的绝佳起点。
  • 不恢复余数法通过巧妙的算法优化,在保持较低硬件成本的同时获得了显著的性能提升,是大多数通用处理器采用的方案。
  • 阵列除法器则代表了对性能的极致追求,适用于那些“不计成本,只求最快”的特定应用领域。

希望本文能帮助你彻底搞懂除法器这个硬核知识点。如果你对计算机组成有更多兴趣,不妨深入研究一下更高级的除法算法,如SRT除法 或牛顿-拉夫逊迭代法 ,它们在现代超标量处理器中扮演着更重要的角色。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐