为什么 2 的补码符号扩展通过添加符号位的副本来工作?

car*_*ass 2 binary assembly bit-manipulation twos-complement sign-extension

我们以将 16 位有符号数符号扩展为 32 位寄存器为例,例如mov $+/-5, %ax movswl %ax, %ebx

有两种可能的情况:

  1. 高位为零(数字为正)。这是非常容易理解和直观的。例如,如果我有数字5,则用零填充左侧很容易理解。例如:

                      00000000 00000101    # 5 (represented in 16 bits)
    00000000 00000000 00000000 00000101    # 5 (represented in 32 bits)
    
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然而,对我来说最难理解的是当它是负数并且我们进行符号扩展时。例子:

                      11111111 11111011    # -5 (represented in 16 bits)
    11111111 11111111 11111111 11111011    # -5 (represented in 32 bits)
    
    Run Code Online (Sandbox Code Playgroud)

是的,我知道我们只是用 填充高位1。但是什么让它发挥作用呢?也许对二进制数的“属性”的解释可以帮助我更好地理解这一点。

Pet*_*des 5

对于n+12 位的补码:

  • 高位(符号位)有位值-(2^n)
  • 下一个最高位有位值2^(n-1),依此类推(普通二进制位值)

例如,在 8 位 2 的补码中,仅设置 MSB 的位模式表示值-128 = -(2^7)。设置前两位后,它代表-128 + 64 = -64


当我们扩展 1 位时,原始符号位现在是带有位置值的“常规”位,+(2^n)而不是-(2^n),因此现有位表示的值现在2^n + 2^n = 2^(n+1)高于原始值。(或者如果该位为零则相同)。

新符号位的位值为-(2^(n+1)),因此复制原始符号位正是我们平衡位值变化所需的。(或者如果为零则保持不变)。

当然,一位的过程可以通过重复任意数量的位来概括。

(通常我们会使用n= 总位数,例如对于 8 位 2 的补码,n=8 而不是 n=7。那么 MSB 的位置值为-2^(n-1),并且通过用新的符号位扩展来更改其含义,2^n如果它是放。)


有关位如何表示值的更多信息,请参阅维基百科:https://en.wikipedia.org/wiki/Two%27s_complement#Converting_from_two's_complement_representation - 2 的补码文章非常好,但没有详细说明为什么复制符号位作品。

您还可以在纸上尝试一些小示例,例如符号从 4 位扩展到 5 位。 -1(全一)将是一个很好的开始值,使数学变得简单。或者0b1000(-8)是另一个不错的选择。

Google 发现https://andybargh.com/binary-sign-extension/可以通过一个 8 位示例运行。