# 3.5.3 移位操作

最后一组是移位操作,先给出移位量,然后第二项给出的是要移位的数。可以进行算术和逻辑右移。移位量可以是一个立即数,或者放在单字节寄存器 %cl 中。(这些指令很特别,因为只允许以这个特定的寄存器作为操作数。)原则上来说,1 个字节的移位量使得移位量的编码范围可以达到 28 - 1 = 255。x86-64 中,移位操作对 w 位长的数据值进行操作,移位量是由 %cl 寄存器的低 m 位决定的,这里 2m = w。高位会被忽略。所以,例如当寄存器 %cl 的十六进制值为 0xFF 时,指令 salb 会移 7 位,salw 会移 15 位,sall 会移 31 位,而 salq 会移 63 位。

如图 3-10 所示,左移指令有两个名字:SAL 和 SHL。两者的效果是一样的,都是将右边填上 0。右移指令不同,SAR 执行算术移位(填上符号位),而 SHR 执行逻辑移位(填上 0)。移位操作的目的操作数可以是一个寄存器或是一个内存位置。图 3-10 中用 >>A(算术)和 >>L(逻辑)来表示这两种不同的右移运算。

练习题 3.9 假设我们想生成以下 C 函数的汇编代码:

long shift_left4_rightn(long x, long n)
{
    x <<= 4;
    x >>= n;
    return x;
}

下面这段汇编代码执行实际的移位,并将最后的结果放在寄存器 %rax 中。此处省略了两条关键的指令。参数 xn 分别存放在寄存器 %rdi%rsi 中。

long shift_left4_rightn(long x, long n)
x in %rdi, n in %rsi

shift_left4_rightn:
    movq %rdi, %rax          Get x
    ____________________     x &lt;&lt;= 4
    movl %esi, %ecx          Get n (4 bytes)
    ____________________     x >>= n

根据右边的注释,填出缺失的指令。请使用算术右移操作。