为什么-1的补码是全1(11111111)?-128的补码是10000000?

首先需要知道:二进制补码表示的正数实际上左侧有无限多个0,而负数有无限多个1.只是为了适应硬件的宽度,二进制表示的数的前导位被隐藏了。

举例

下面看一下64位的 − 4 t e n -4_{ten} 4ten的补码(以64位机器(机器里面存的是补码)为例):

00000000 , 00000000 , 00000000 , 00000000 , 00000000 , 00000000 , 00000000 , 0000010 0 t w o = [ 4 ] 补 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000100_{two}=[4]_{补} 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000100two=[4]
11111111 , 11111111 , 11111111 , 11111111 , 11111111 , 11111111 , 11111111 , 1111110 0 t w o = [ − 4 ] 补 11111111,11111111,11111111,11111111,11111111,11111111,11111111,11111100_{two}=[-4]_{补} 11111111,11111111,11111111,11111111,11111111,11111111,11111111,11111100two=[4]
下标two表示二进制,下标ten表示十进制。

我们把 [ − 4 ] 补 [-4]_{补} [4] [ 4 ] 补 [4]_{补} [4]相加会得到什么呢?

[ − 4 ] 补 + [ 4 ] 补 = 00000000 , 00000000 , 00000000 , 00000000 , 00000000 , 00000000 , 00000000 , 0000010 0 t w o + 11111111 , 11111111 , 11111111 , 11111111 , 11111111 , 11111111 , 11111111 , 1111110 0 t w o = 1 , 00000000 , 00000000 , 00000000 , 00000000 , 00000000 , 00000000 , 00000000 , 0000010 0 t w o [-4]_{补}+[4]_{补}=00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000100_{two}\\+11111111,11111111,11111111,11111111,11111111,11111111,11111111,11111100_{two}\\=1,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000100_{two} [4]+[4]=00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000100two+11111111,11111111,11111111,11111111,11111111,11111111,11111111,11111100two=1,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000100two
我们发现 64位补码相加得到 2 64 2^{64} 264!

下面求8位的 − 4 t e n -4_{ten} 4ten的补码

已知 有符号数 − 4 t e n = 1000010 0 t w o -4_{ten}=10000100_{two} 4ten=10000100two,

根据口诀:负数的补码=负数的原码取反(符号位不变,数据位取反)+1
可以得到: [ − 4 ] 补 = 1111101 1 t w o + 0000000 1 t w o = 1111110 0 t w o [-4]_{补}=11111011_{two}+00000001_{two}=11111100_{two} [4]=11111011two+00000001two=11111100two,

4 t e n 4_{ten} 4ten的补码仍然是原码,即 [ 4 ] 补 = 0000010 0 t w o [4]_{补}=00000100_{two} [4]=00000100two,

我们把 [ − 4 ] 补 [-4]_{补} [4] [ 4 ] 补 [4]_{补} [4]相加会得到什么呢?

[ − 4 ] 补 + [ 4 ] 补 = 1111110 0 t w o + 0000010 0 t w o = 1 , 00000000 [-4]_{补}+[4]_{补}=11111100_{two}+00000100_{two}=1,00000000 [4]+[4]=11111100two+00000100two=1,00000000

我们发现 8位补码相加得到 2 8 2^{8} 28!

归纳

二进制补码得名于下述规则:一个n位的数与其n位的相反数做无符号加法,结果为 2 n 2^n 2n,因此,x的相反数(或相补数)-x 等于 2 n − x 2^n-x 2nx,或叫“二进制补码”

以n=8位为例,1的二进制表示为00000001,则 -1的二进制补码可以由上面的公式写出来
[ − 1 ] 补 = 2 n − 1 = 2 8 − 1 = 1 , 00000000 − 00000001 = 11111112 − 00000001 = 11111111 [-1]_补=2^n-1=2^8-1=1,00000000-00000001=11111112-00000001=11111111 [1]=2n1=281=1,0000000000000001=1111111200000001=11111111
注:这里11111112仅仅是方便计算,实际二进制中逢二进一,还是100000000.

同样的,我们来看-128的情况。

对于 12 8 t e n = 2 7 = 10000000 128_{ten}=2^7=10000000 128ten=27=10000000 ,这里的n=8,根据补码的定义:

[ − 128 ] 补 = 2 8 − 128 = 1 , 00000000 − 10000000 = 11111112 − 10000000 = 10000000 [-128]_{补}=2^8-128=1,00000000-10000000=11111112-10000000=10000000 [128]=28128=1,0000000010000000=1111111210000000=10000000

综上,求1个负数(-x)的补码,只需要用 2 n − x 2^n-x 2nx即可,这里的n表示这个负数的二进制表示位数。

后记:这个问题在《计算机组成与设计-硬件/软件接口》一书中有详细的解释。

你可能感兴趣的:(计算机组成原理)