右移算术

Shift right arithmetic

请看下面的代码:

addi $t1,$zero,-32
sra $t0,$t1,2

-32 = 0010 1111 1111

在 >> 2 之后:0000 1011 1111 = -26

但是移位后正确答案应该是-8,这是怎么回事??

0010 1111 1111

这好像是一个12位的数字。 MIPS CPUs 使用 32 位数字。

因此无论您的程序执行哪种操作: 0010 1111 1111 位无法描述寄存器的全部内容!

-32 = 0010 1111 1111

0000 1011 1111 = -26

我尝试了不同的常用二进制数存储和写入方式,包括 BCD!

我不知道 0010 1111 11110000 1011 1111 应该如何表示数字 -32 和 -26!

就像十进制数一样,二进制数通常是从右向左书写的:

最右边的数字的值为 2^0 (1),它左边的数字是 2^1 (2),它左边的数字是 2^2 (4) 等等。

这意味着000 ... 000 1011 1111是128+32+16+8+4+2+1 = 191。

我也看到有人用另一种方式写数字(所以他们把 191 写成 11111101)。但是,这样的人要记住,"left"和"right"(sra=shiftright算术)这两个词是反义的!

-32 = ...

负数存储在CPU寄存器中有不同的方法:

  • 符号和正数
    (通常用于 floating-point)
  • 补码
    (用于 IPv4、TCP 和 UDP 中的校验和计算)
  • 带偏移量的整数
    (常用于fixed-point算术)
  • (伪)对称数系
    (三进制计算设备的首选方式,但通常不用于二进制计算机)
  • 补码

几乎所有现代二进制计算机和 CPU 都使用 补码 。对于 MIPS CPUs.

也是如此

因为你写了“-32 = 0010 1111 1111”,所以我假设你不明白补码的工作原理:

在二进制补码系统中,左边的位是数字的符号。如果左边的位是 1,则数字是负数。如果左位为零,则数字为正数或零。

(请注意,对于我上面提到的所有存储负数的方法,这 不是 正确。)

通过反转二进制补码数 x 的所有位,我们得到数字 -(x+1)。这意味着:

 31 =   32-1  = 00...0011111
-32 = -(31+1) = 11...1100000

after >> 2 ...

...我们得到的结果是 111111...111000:

删除了右边的两位,在左边添加了两位"new"。因为这是一个算术移位,所以这是通过 "copying" 原数的左边位来完成的:

左边的位是“1”,所以在左边加了两个“1”位。

But the correct answer should be -8 after shifting, how does that happen??

“111111...111000”的左边位是 1。所以这是一个负数。

现在我们再次应用"invert all bits"规则; x是寄存器中的值:

x      = 111...111000
-(x+1) = 000...000111 = 7

-(x+1) = 7

这意味着:x = (-8)