一眼看懂二进制补码的计算方法

时间:2022-10-01 19:52:52

一眼看懂二进制补码的计算方法

最近,我仔细研究了下linux下,C程序的编译和链接过程。反汇编和查看二进制时,难免看到大量整数的二进制表示,特别是负数,例如0xfffffffc,这个是多少?记得有个转换方法,首先这个数是一个负数,它的绝对值是 ~(0xfffffffc)+ 1 = 0x00000003 + 1 = 4, 所以值为-4

那么这个取反加一的方法是怎么得来的呢?我想不起来了。就自己鼓捣了一下:

我们考虑两个8bit寄存器A,B相加:

比如 A=128, B=132, 我们把计算机计算结果用[]括起来:

[A + B] = [0x80 + 0x84] = [1000 0000 + 1000 0100] = (1 0000 0100) 8bits截断 = 0000 0100 = 4
      = A + B - 256 = A + B - 2^8

其实对于任何nbits寄存器,[An + Bn + 2^n]= ( An + Bn - 2^n ) + 2 ^n = An + Bn

即:[An + Bn + 2^n] = An + Bn

我们知道在二进制电路中,减法实际上也是通过加法来实现的。

因为 ,由于这里还没有引入负数的表示,先假设An > Cn, 则[An + (2^n - Cn )]= (An - Cn) + 2^n = An - Cn

也就是 ,如果我们要计算 An - Cn其实,计算机可以直接用An加上2^n - Cn( > 0)来计算。

所以我们就把 2^n - Cn叫做-Cn的补码,对应的二进制值就是-Cn的二进制表示, 为了不和正整数冲突,考虑到最高位对负数来说始终为1, 就称为了符号位,对应的正整数也只能使用余下的n-1位来表示。

对了刚才我们是假设An > Cn,现在我们来看看,如果把2^n - Cn对应的二进制定义为-Cn的二进制格式。

那么,当 An < Cn时,[An + (2^n - Cn )]是否也对应着An - Cn的二进制格式呢?

这个是显然的。因为 An + (2^n - Cn ) = 2^n - (Cn - An) 也就是 - (Cn - An)的二进制表示。

既然体会到了 2^n - Cn就是-Cn的补码,那么补码的计算很容易得出:

   2^n  =           2^n-1             + 2^n-2           ... + 2^2      + 2^1         + 1    + 1
   Cn   =  bit(n-1)*2^n-1  +  bit(n-2)* 2^n-1 ...+ bit(3)* 2^2 +  bit(1)*2^1 +  bit(0)*1.

2^n-Cn  = ~bit(n-1)*2^n-1  +  ~bit(n-2)* 2^n-1 ...+ ~bit(3)* 2^2 +  ~bit(1)*2^1 +  ~bit(0)*1 + 1.
        = ~Cn + 1

就是

  -Cn的补码 = 2^n - Cn = = ~Cn + 1

看来很容易懂啊。