Language agnostic 把我的头绕在数字的硬件表示上:一个假设的2';s补语问题
这是一个非常幼稚的问题(我知道),但我认为这将是考虑CPU基本指令集实际如何执行的一个很好的起点: 在2的补码系统中,您不能反转实现所能表示的最负数的符号。这种情况的理论原因很明显,因为最负数的否定将超出实现的范围(范围总是类似于Language agnostic 把我的头绕在数字的硬件表示上:一个假设的2';s补语问题,language-agnostic,hardware,math,twos-complement,instruction-set,Language Agnostic,Hardware,Math,Twos Complement,Instruction Set,这是一个非常幼稚的问题(我知道),但我认为这将是考虑CPU基本指令集实际如何执行的一个很好的起点: 在2的补码系统中,您不能反转实现所能表示的最负数的符号。这种情况的理论原因很明显,因为最负数的否定将超出实现的范围(范围总是类似于 -128至127) 然而,当你尝试对最负的数字进行求反运算时,实际发生的情况是非常奇怪的。例如,在8位表示法中,最大负数为-128,或二进制中的1000 0000。通常,要对一个数字求反,你需要翻转所有的位,然后加一。但是,如果您尝试使用-128执行此操作,您将得到:
-128至127) 然而,当你尝试对最负的数字进行求反运算时,实际发生的情况是非常奇怪的。例如,在8位表示法中,最大负数为-128,或二进制中的1000 0000。通常,要对一个数字求反,你需要翻转所有的位,然后加一。但是,如果您尝试使用-128执行此操作,您将得到:
1000 0000 ->
0111 1111 ->
1000 0000
和你开始时的号码一样。出于这个原因,我们称之为“奇怪的数字”
在同一篇文章中,上面的否定
被检测为溢出情况,因为最高有效位有进位,但没有进位
所以我的问题是:A) 这到底是什么意思?和
B) 似乎CPU每次执行基本算术运算时都需要执行额外的错误检查步骤,以避免与此求反相关的事故,从而产生显著的开销。如果是这样的话,为什么不直接截断可以表示的数字范围,将奇怪的数字去掉(即-127到127表示8位)?如果不是这样的话,如何在不产生额外开销的情况下实现这种错误检查?这不是CPU进行另一次检查,而是晶体管被安排在发生这种情况时注意到。它们是这样建造的,因为工程师们在开始设计之前选择了两个补充 结果是,它发生在与返回非溢出结果相同的时钟周期内
它是如何工作的 “添加1”阶段实现级联逻辑:从LSB开始,每个位依次接受真值表
old-bit carry-in new-bit carry-out
-------------------------------------
0 0 0 0
0 1 1 0
1 0 1 0
1 1 0 1
(即新位=旧位异或进位
和进位=旧位和进位
)。LSB的“进位”是我们正在添加的1,其余的位是前一位的“进位”(这就是为什么必须级联完成)
最后一个电路只是为
有符号溢出=(进位和不进位)
添加一个电路。MSB的进位用作标志,指示
需要更多的位子。如果没有它,我们将有一个1的系统,当我们绕过去时,没有任何检测方法
在模运算中,您不处理数字,而是处理
具有相同余数的数的集合。这样
一个系统,在把1加到127之后,你会得到−128,你会的
得出+128和+128的结论−128属于同一等价类
如果你把自己限制在这个范围内−127到+127,你呢
必须重新定义加法,因为127+1=−这是胡说八道
当计算机呈现给您时,二的补码算法是
基本上是模块运算,能够检测溢出
这就是将0001
添加到
0111
。您可以看到,在MSB中,进位和进位是
不同的:
0 0 0 1
| 0 | 1 | 1 | 1
| | | | | | | |
v v v v v v v v
0 <- ADD <-1- ADD <-1- ADD <-1- ADD <- 0
^ | ^ | | |
v v v v
1 0 0 0
01
| 0 | 1 | 1 | 1
| | | | | | | |
v v v v v v v
0首先,wikipedia文章指出,它不能从负号否定为有符号数。它们的意思是,它需要9位来表示正128,这是8位寄存器无法做到的。如果将负符号转换为正无符号,那么就有足够的位。当你否定0x80时,硬件应该给你0x80,因为这是正确的答案
对于加法、减法、乘法等,二进位的加法和小学的十进制数学没有什么不同。您将二进制数排成一行,添加列,该列的结果是最低有效位,其余的则转入下一列。例如,将0b001添加到0b001
1
001
001
===
010
1.
001
001
===
010
将最右边一列中的两个1相加,结果为0b10(2个十进制数),写入0,然后进行1运算,1加0加0等于1,无需进行任何运算,0加0等于0,结果为0b010
最右边的一列,其中1加1是0b10,我们写0,携带1,携带1的同时是最右边一列的进位,也是第二列的进位。同样,在纸笔数学中,我们通常只讨论非零时的进位,但如果你想一想,你总是携带一个数字,比如我们的第二列,一加零就是一进位
你可以把两个补数的否定看作是倒过来加上一,或者把位倒过来,然后不倒过来,或者取零减去数字的结果
你们们可以用铅笔和纸在二进制中进行减法运算,这会使你们们的头在借用十进制时受伤,但还是有效的。对于你要问的问题,想一想倒过来加一个
如果你把它降到比8更少的位,你就更容易理解它,3是一个可管理的数字,它从那里开始扩展
因此,下面的第一列是输入,第二列是反转版本,第三列是第二列加一。第四列是msbit的进位,第五列是msbit的进位
000 111 000 1 1
001 110 111 0 0
010 101 110 0 0
011 100 101 0 0
100 011 100 1 0
101 010 011 0 0
110 001 010 0 0
111 000 001 0 0
000 111 000 1 1
001 110 1
00+1 = 001
01+1 = 010
10+1 = 011
11+1 = 100
OverflowFrom
Returns 1 if the addition or subtraction specified as its parameter
caused a 32-bit signed overflow. [...]
Subtraction causes an overflow if the operands have different signs,
and the first operand and the result have different signs.
NEG
[...]
V Flag = OverflowFrom(0 - Rm)