如果你研究现代微处理器,你可能会注意到它与老式机械计算设备(如机械计算器)之间的相似之处。更具体地说,微处理器中的算术逻辑单元(ALU)与老式机械计算器有许多相似之处。ALU 可以被认为是微处理器的计算器。它读取存储在寄存器(register)中的数字,执行加减或移位操作,并将结果存储回另一个寄存器。
微处理器内部的算术逻辑单元执行算术运算。寄存器名为 r1, r2 和 r3。
这些基本操作与计算器所执行的操作完全相同。它有三个寄存器来保存计算过程中使用的数字:
输入寄存器:一个 5 位的寄存器,你可以拉动杆来定义输入数字。
累加寄存器:一个 13 位的寄存器,用于保存多次计算的结果。
计数寄存器:一个 8 位数的寄存器,用来记录你做了多少加法。
我不会在这里详细解释微处理器 ALU 或老式机械计算器。我们将穿越更远的时间回到算盘。这种不同形式的手动计算机器早在罗马时代之前就存在了。
为什么要了解算盘和它的操作?因为理解算盘可以让你看到一些更深层次的东西,将几千年前处理数字的方法与现代微处理器的方法联系起来。现代微处理器是如此复杂,当你试图理解它们时,你很容易“误入歧途”。
算盘就像微处理器的 ALU 一样。现代计算机基于二进制数系统,其中每个数字称为位。下图演示的算盘可以处理最多四个十进制数字。算盘上的每一列代表数字中的一个数字。
从右边开始的第一列是个位,第二列是十位,第三列是百位,以此类推。这意味着,如果我想在算盘上表示数字 4023,那么我就按上图所示排列珠子。有了这种安排,加减法就很容易执行了。如果我想加 12,我只要在个位上多拉两颗珠子,在十位上多拉一颗珠子。
加减法非常简单,所以让我们看看如何在算盘上做乘法。乘法运算的方式非常类似于老式机械计算器和早期微处理器的乘法运算方式,它们只有 ALU,没有专用的乘法硬件。
用算盘乘法
我们将做一个简单的乘法:32 × 4,结果应该是 128。为了执行此操作,我们为每一列指定特定的含义。前两列被转换为计数器寄存器,而第三列被定义为输入寄存器。最后,我们让最后两列作为累加寄存器,它将保存最终结果。
乘法可以被认为是进行多次加法运算。在本例中,我们将对 4 相加 32 次。
乘以个位列
我们先给累加器加 4 次。单列中的四颗珠子向下移动。为了记录我们已经添加了四颗珠子的数量,我们从计数器上移动一颗珠子。实际上,我们从 32 开始倒数到 0。
我们在累加器中再加 4,计数器减少到 30。此时,累加器的值为 8。我们还要再加 30 个 4 个。
乘以十位列
在“个位”列上移动四颗珠子 30 次以上会很乏味。幸运的是,我们不必这么做。相反,我们执行一个移位操作来加快加法的速度。我们把每一颗移动的珠子算作十乘以四。这是怎么做到的?每次我们移动计数器十位上的一个珠子,我们就移动累加器十位上的四个珠子。执行此操作一次,计数器从 30 减少到 20,累加器增加到 48(8 + 4 × 10) 。
我们再次重复相同的操作,从而将计数器从 20 减少到 10,并向累加器添加另一个 40,现在它的值为 88(48 + 4 × 10)。
注意,在上图中,我们不能再向下移动 4 个珠子,因为累加器的十位列中只剩下 2 个珠子。我们需要使用第三列,用累加器表示百位。我们用十位上的十颗珠子换百位上的一颗珠子。
此外,十位总共需要 12 颗珠子,我们用它来交换百位的 1 颗珠子和十位的 2 颗珠子。此时,我们已经花光了计数器上的所有珠子,可以看到最终的结果是 128。
移位操作
用算盘、机械计算器或 ALU 都不能直接做乘法和除法。然而,我们可以轻易地用 10 的倍数相乘。用 10、100 或 1000 乘以一个输入数字很容易,你所要做的就是移动 1、2 或 3 列的珠子。做 2 × 4 需要移动个位列中的 4 个珠子两次。如果想执行 20 × 4,则将十位列中的四个珠子移动两次。如果是 200 × 4,这意味着在百位列中移动 8 个珠子。你所做的实际上是加法运算和移位运算的结合。
如果你看机械计算器,你将看到累加寄存器位于一个滑动条上。向左滑动一个缺口,从输入寄存器中添加的数字将是原来的十倍。向左边滑动两个凹槽,输入的数字就会变为原来的 100 倍。我们也可以向右滑动,使相加的数字变小。一个有趣的效果是,滑动杆做移位,它也影响计数寄存器。假设你指定输入寄存器为 42。接下来,将杆向左滑动两个凹槽。当你转动手柄将输入加到累加器中时,你将加 4200。计数寄存器上会显示 100。因此,它看起来就像你拧了手柄一百次一样。换句话说,移位允许我们大幅减少执行加法的次数。
这些移位操作与我们在算盘上实现的没有什么不同。关键的区别在于,你需要通过手动移动珠子来更新累加器和计数器。
微处理器中移位运算的使用
移位运算帮助我们加快微处理器 ALU 上的乘法和除法运算。因为现代的微处理器是用二进制数字系统操作的,移位操作的是 2 的倍数的多个输入。因此,我们不是用 10、100、1000 或 10000 乘以输入,而是用 2、4、8、16、32 等等乘以输入。
开始编程时,这种知识实际上很有用。在 20 世纪 90 年代初,个人电脑的乘法运算非常缓慢。我们必须使用乘法来计算像素在图形存储器中特定 x, y 坐标处的位置。因为屏幕分辨率是 320 × 240,你必须把 y 坐标乘以 320,然后加上 x 坐标,才能得到屏幕内存中的位置。
关键是,我必须将任意数 y 乘以 320 无数次。这是非常慢的。解决方案是将计算改为移位和加法的组合。以下是一个简介:
用两个移位操作和一个加法替换乘法,这给了一个关键的速度提升。
本文来自微信公众号:老胡说科学 (ID:LaohuSci),作者:我才是老胡