任何时候你想处理这些类型的 ALU 项目,无论是加、减、乘等,从 2 或 3 位数字开始,比 32 或 64 位数字更容易处理。在 2 位或 3 位之后,无论是 22 位还是 2200 位都无关紧要,从那时起,它的工作原理完全相同。基本上,如果您想制作一个包含所有 3 位操作数及其结果的表,以便您可以直观地检查整个表,但是您可以手动创建一个包含所有 32 位操作数和所有 32 位操作数及其结果的表,不能这样做在合理的时间内手动进行,并且无法直观地检查整个表。
现在二进制补码,这只是一种表示正数和负数的方案,它不是有原因的任意事物,疯狂的原因是您的加法器逻辑(这也是减法器使用的相同)乘数使用的东西)不关心未签名或签名。它不知道区别。在我的三位世界中,程序员关心的是位模式 0b111 可能是正七(+7),也可能是负七。相同的位模式,将其提供给加法逻辑,得到相同的结果,而得到的答案我可以选择解释为无符号或二进制补码(只要我将操作数和结果全部解释为无符号或全部作为二进制补码)。二进制补码还具有对负数设置最高有效位 (msbit) 的特性,对于正数则为零。所以它不是符号加幅度,但我们仍然谈论 msbit 是符号位,因为除了它告诉我们的两个特殊数字,数字的符号,其他位实际上告诉我们它们的幅度只是不是像符号+幅度符号中那样的无符号幅度。
所以,整个问题的关键是理解你的极限。对于 3 位无符号数,我们的范围是 0 到 7、0b000 到 0b111。对于 3 位有符号(二进制补码)解释,我们的范围是 -4 到 +3(0b100 到 0b011)。现在如果你添加 7+1 将我们限制为 3 位,0b111 + 0b001 = 0b1000
但我们只有一个 3 位系统,所以 0b000,7+1 = 8,我们不能在我们的系统中表示 8,所以这是溢出,因为我们碰巧将这些位解释为无符号,我们查看“无符号溢出”,也称为进位位或标志。现在,如果我们采用相同的位但将它们解释为有符号,则 0b111 (-1) + 0b001 (+1) = 0b000 (0)。减一加一是零。没有溢出,没有设置“有符号溢出”......什么是有符号溢出?
首先什么是“无符号溢出”。
无论我们的寄存器中有多少位,“一切都一样”的原因与以 10(十进制)为基数的小学数学没有什么不同。如果你添加 9 + 1,它们都在个列中,你说 9 + 1 = 零携带 1。你将 1 带到十列,然后 1 加 0 加 0(你在十列中填写了两个零)是 1 携带零。您在十列中有一个 1,在个列中有一个零:
1
09
+01
====
10
如果我们声明我们仅限于个列中的数字,那么十列就没有空间了。那么进位位非零意味着我们有一个溢出,为了正确计算我们需要另一列的结果,与二进制相同:
111
111
+ 001
=======
1000
7 + 1 = 8,但是如果我们声明一个 3 位系统,我们不能做 8,我们可以在设置进位位的情况下做 7 + 1 = 0。这就是补码之美的所在:
111
111
+ 001
=======
000
如果您查看上述三位加法,则无法通过查看是否设置进位位的 7 + 1 = 0 或 -1 + 1 = 0 来判断。
因此,对于无符号加法,正如我们从小学开始就知道的那样,将非零的东西转移到下一列意味着我们已经溢出了那么多占位符,需要一个占位符,一个列来保存实际答案。
签名溢出。学术上的答案是msbit 列的进位与进位不匹配。让我们在我们的 3 位世界中举一些例子。因此,对于二进制补码,我们仅限于 -4 到 +3。因此,如果我们添加 -2 + -3 = -5 将无法正常工作?为了弄清楚减二是多少,我们进行反转并添加一个 0b010,反转 0b101,添加一个 0b110。减三是 0b011 -> 0b100 -> 0b101
所以现在我们可以这样做:
abc
100
110
+ 100
======
010
如果您查看 b 下的数字,即 msbit 列的“进位”,a 下的数字 1,是进位,这两个不匹配所以我们知道存在“有符号溢出”。
让我们试试 2 + 2 = 4:
abc
010
010
+ 010
======
100
你可能会说,但这看起来是对的,肯定是无符号的,但是我们在这里做有符号的数学运算,所以结果实际上是 -4 而不是正的 4. 2 + 2 != -4。b 下的进位是 1,msbit 的进位是 0,进位和进位不匹配。 签名溢出。
无需查看进位(或进位)即可计算出带符号溢出的捷径。 有符号溢出,否则无符号溢出。opa 是一个操作数, opb 是另一个操作数, res 结果。if ( msbit(opa) == msbit(opb) ) && ( msbit(res) != msbit(opb) )
010
+ 010
======
100
取这个+2 + +2 = -4。msbit(opa) 和 msbit(opb) 相等,结果 msbit 不等于 opb msbit 所以这是一个有符号溢出。您可以使用此表来考虑它:
x ab cr
0 00 00
0 01 01
0 10 01
0 11 10 signed overflow
1 00 01 signed overflow
1 01 10
1 10 10
1 11 11
这张表是所有可能的组合,如果进位、操作数 a、操作数 b、进位和单列的结果位 将头侧向左侧排序,看到 x 是进位,a 和 b 列是两个操作数。 cr
作为一对是xab
011 的结果意味着 0+1+1 = 2 十进制是 0b10 二进制。因此,按照我们规定的规则,如果进位和进位不匹配,那就是有符号溢出. 那么 x 列中的项目与 c 列中的项目不匹配的两种情况表示为 a 和 b 输入相互匹配但结果位与 a 和 b 相反的情况。因此,假设规则是正确的,这个不需要知道进位位是什么的快速快捷方式会告诉您是否存在有符号溢出。
现在您正在阅读一本 H&P 书籍。这可能意味着 mips 或 dlx,mips 或 dlx 都不像大多数其他处理器那样处理进位和签名标志。mips 不是最好的第一个指令集 IMO 主要是因为这个原因,他们的方法在任何方面都没有错,但是作为一个古怪的人,你将永远花在不同的思考上,并且在使用大多数其他处理器时不得不进行翻译。如果您学习了典型的 znvc 标志(零标志、负标志、v=有符号溢出、c=进位或无符号溢出)方式,那么您只需在转到 mips 时进行翻译。通常这些是在每个 alu 操作上计算的(对于非 mips 类型的处理器)你会看到有符号和无符号溢出正在计算加减法。(我习惯了较旧的 mips,也许这一代的书和当前的指令集有一些不同)。在了解了上述关于加法器电路如何不关心有符号与无符号的所有内容之后,在 mips 的开头将其称为 addu add unsigned 是 mips 的一个大问题,它确实使您陷入错误的心态来理解这么简单的事情。导致人们相信有符号加法和无符号加法之间存在差异。只有溢出标志的计算方式不同。现在乘法和除法肯定存在二进制补码与无符号差,理想情况下您需要有符号乘法和无符号乘法或者你需要处理这个限制。
我推荐一个简单的(取决于你的位操作有多强和二进制补码) 练习,你可以用一些高级语言编写。基本上取所有无符号数 0 到 7 的组合加到 0 到 7 并保存结果。以十进制和二进制打印(操作数三位,结果四位),如果结果大于 7,则打印溢出。使用带符号的变量重复此操作,使用数字 -4 到 +3 添加到 -4 到 +3。打印带有 +/- 符号的十进制和二进制。如果结果小于 -4 或大于 +3 则打印溢出。从这两个表中,您应该能够看到上面的规则是正确的。严格查看允许大小的操作数和结果位模式(在这种情况下为三位),您将看到加法运算给出相同的结果,给定输入对的相同位模式与这些位模式是否被视为无符号或二进制补码无关。您还可以验证无符号溢出是当结果需要使用第四列时,msbit有一个进位。当进位与进位不匹配时进行签名,您可以使用查看操作数和结果的 msbits 的快捷方式看到。更好的是让你的程序进行这些比较并打印出一些东西。因此,如果您在表中看到结果大于 7 的注释,并且在表中看到结果中设置了位 3 的注释,那么您将看到无符号表始终如此(仅限于输入 0至 7)。还有更复杂的,有符号溢出, 总是在结果小于 -4 且大于 3 并且操作数高位匹配且结果高位与操作数不匹配时。
我知道这是超长而且非常基本的。如果我在这里完全错过了标记,请发表评论,我将删除或重写此答案。
另一半与魔法相得益彰。硬件没有减法逻辑。“转换”为二进制补码的一种方法是“反转和加一”。如果我想使用二进制补码减去 3 - 2 ,实际发生的情况与 +3 + (-2) 相同,并且为了从 +2 到 -2,我们反转并加一。看看我们小学的加法,你注意到第一列进位的洞了吗?
111H
111
+ 001
=======
1000
我在洞所在的位置上方放了一个 H。那么进位被添加到操作数对吗?我们的加法逻辑不是一个二输入加法器它是一个三输入加法器是吗?大多数列必须添加三个一位数才能计算两个操作数。如果我们在第一列上使用三输入加法器,现在我们有一个地方可以......加一个。如果我想减去 3 - 2 = 3 + (-2) = 3 + (~2) + 1 这是:
1
011
+ 101
=====
在我们开始并填写之前是:
1111
011
+ 101
=====
001
3 - 2 = 1。
逻辑的作用是:
如果添加则进位= 0; b 操作数不反转,进位不反转。如果减去则进位= 1; b 操作数被反转,进位可能被反转。
上面的加法显示了一个执行,我没有提到这是一个无符号操作 3 - 2 = 1。我使用了一些二进制补码技巧来执行一个无符号操作,因为无论我是否将操作数解释为有符号或unsigned 相同的规则适用于加法或减法。为什么我说进位可能被反转是因为有些处理器会反转进位而有些则不会。它与级联操作有关,假设一个 32 位加法逻辑并使用进位标志和带进位的加法或带借位的减法指令创建 64 位加法或减法,或基址寄存器大小的任何倍数。假设您在 32 位系统中有两个 64 位数字 a:b + c:d 其中 a:b 是 64 位数字,但它保存在两个寄存器 a 和 b 中,其中 a 是上半部分,b 是下半部分一半。所以 a:b + c:d = e:f 在一个 32 位无符号系统上,它有一个进位并加进位:
add f,b,d
addc e,a,c
加法从状态寄存器进位标志的最高位通道中离开其进addc
位位,指令是带进位的加法运算,取操作数 a+c,如果进位位被设置,则再加一个。a+c+1 将结果放入 e 并将进位放入进位标志中,因此:
add f,b,d
addc e,a,c
addc x,y,z
是96位加法,等等。这里又是一些对 mips 非常陌生的东西,因为它不像其他处理器那样使用标志。有符号进位的反转或不反转是在特定处理器的借位减法上。对于减法:
如果减去则进位= 1; b 操作数被反转,进位可能被反转。
对于借位减法,您必须说如果状态寄存器中的进位标志指示借位,则进位为 0,否则进位为 1,并且您必须将进位输入状态寄存器以指示借位.
基本上对于正常的减法,一些处理器将 b 操作数取反并在输入中进行并在输出中执行,一些处理器将 b 操作数取反并在输入中进行,但在输出时不取反。然后当你想做一个条件分支时,你需要知道进位标志是大于还是小于(通常语法会有一个分支如果大于或小于分支,有时会告诉你如果进位哪个是简化分支如果进行清除,则设置或分支)。(如果你没有“明白”我刚才所说的那是另一个同样长的答案,只要你正在研究 mips,它就没有任何意义)。