



理解了 2 的补码之后,我们再回到右移运算这个话题。之前讲过,在右移运算中,移动后空出来的高位有用 0 填充和用 1 填充两种情况。如果将二进制数想象成图案而不是数值,在右移时就会用 0 来填充高位,就像图案在霓虹灯牌上向右滚动的感觉,这种做法称为 逻辑右移 ( 图 2-9 )。
    图 2-9 图案右移(逻辑右移)
在需要将二进制数作为有符号的数值来运算时,右移时用原数符号位的值(0 或 1)来填充高位,这种做法称为 算术右移 。当原数是以 2 的补码形式表示的负数时,右移时空出来的高位就会用 1 填充,从而对有符号数进行正确的 1/2、1/4、1/8 等数值运算。而当原数是正数时,高位用 0 来填充就可以了。
下面我们来看一个右移运算的例子。假设我们要将 - 4(= 11111100)右移 2 位,如果是逻辑右移,结果就是 00111111,即十进制的 63。但是,这个结果并不是 - 4 的 1/4,如果用算术右移,结果就是 11111111,正好是以 2 的补码表示的 - 1,这样我们就能正确计算出 - 4 的 1/4 了( 图 2-10 )。
只有在右移运算中才需要区分逻辑移位和算术移位。在左移运算中,只要将空出来的低位用 0 填充,就可以同时满足图案移动(逻辑左移)和乘法运算(算术左移)两种情况的需要了。
    图 2-10 逻辑右移与算术右移的区别
这里还要介绍一下 符号扩展 (sign extension)。当我们要将一个 8 位二进制数在不改变其值的情况下转换成 16 位二进制数或者 32 位二进制数时,就需要使用符号扩展。将 01111111 这样的二进制正数转换成 16 位就是 0000000001111111,这种情况很容易处理,但如果是像 11111111 这样的以 2 的补码表示的负数,该怎样转换呢?其实,转换方法很简单,只要写成 1111111111111111 就可以了。无论是正数,还是以 2 的补码表示的负数,进行符号扩展时都只要用符号位的值(0 或 1)填充高位即可,也就是将符号位直接扩展到高位( 图 2-11 )。
    图 2-11 从 8 位到 16 位的符号扩展方法