补码的算术移位

这个问题在唐朔飞版本的计算机组成原理教程中是这样写的,这本教材应该也是大多数大学计算机组成原理的参考教材

不论是正数还是负数,移位后其符号位均不变,这是算术移位的重要特点。

下面也给出了一张表,解释了移位运算的规则

对于移位运算,左移1位相当于补码对应的 真值 * 2

比如,按照教材中的规则,一个8位二进制补码 11010110,其真值 -42,算术左移1位时,应该变成 10101100,真值 -84,此时没有问题

但是如果此时再往左移一位呢?

按照上面的规则,保留符号位1,应该得到 11011000,真值 -40
是符合唐朔飞教材中的规则的,并且真值 -40-84 * 2 % 128
但是如果使用C++模拟这个过程,会看到真值是 88,即不保留符号位的情况下左移

C++代码如下

需要 C++20 以后代码才能正常运行
C++20 以前编译器会认为对a左移两位是未定义的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <bitset>  
#include <cstdint>
#include <iostream>
using namespace std;

int main() {
// -42的补码
int8_t a = 0b11010110;
int8_t b = a << 2;
int8_t c = 0b11011000; // 预计得到的值

cout << static_cast<int>(c) << endl;

cout << static_cast<int>(a) << endl;
cout << bitset<8>(a) << "\n" << endl;

cout << static_cast<int>(b) << endl;
cout << bitset<8>(b) << endl;
return 0;
}

代码运行结果如下

所以可以得出结论,算术左移是需要将符号位一起移动的,并不是教材上说的符号位始终不变,这个问题王道计算机组成原理2025版进行了修改