我已经看到逻辑左移可以进行 1-31 位的移位。算术右移和逻辑右移以 1 -32 作为移位量。为什么右移和左移之间存在差异?
2 回答
它与某些移位操作的特殊含义有关。来自DDI 0029E
(ARM7TDMI 数据表):
LSL #0 是一种特殊情况,其中移位器进位是 CPSR C 标志的旧值。Rm 的内容直接用作第二个操作数。
....
预期对应于 LSR #0 的移位字段的形式用于编码 LSR #32,其结果为零,Rm 的第 31 位作为进位输出。逻辑右移零是多余的,因为它与逻辑左移零相同,因此汇编器会将 LSR #0(以及 ASR #0 和 ROR #0)转换为 LSL #0,并允许指定 LSR #32。
换句话说,处理器设计者为 赋予了特殊含义LSL #0
,这也意味着没有可能的编码,LSL #32
因为 1..31 的移位量按原样解释,而 0 具有其特殊含义。
LSR #0
并且ASR #0
将由LSL #0
汇编器转换为,因为它们具有相同的含义,这意味着机器代码编码LSR #0
并可以自由用于ASR #0
其他东西;因此他们将 0 的移位量解释为 32 LSR/ASR
。
我相信这与 ARM 桶形移位器有关。基本上 ARM 架构没有真正的移位指令。相反,它使您可以使用桶形移位器作为其他指令的一部分进行移位。
在处理接受移位的指令之前,处理器将检查是否指定了移位。如果不是,则应用的默认班次为 LSL #0。
现在,寄存器的移位量在指令中的 5 位字段或寄存器的底部字节上指定。然而,使用 5 位字段没有额外的开销,而使用寄存器则需要额外的周期。
5 位为您提供 32 个不同的值。因为当我们不想应用任何移位时我们需要一个 0 值,所以 LSL 的可能值范围是 0-31,而 LSR 和 ASR 的范围是 1-32,因为你永远不需要做 LSR # 0 或 ASR #0。
至于 LSR #32 或 ASR #32,如果您想用 0 或 1 设置寄存器并知道要移位的最后一位是什么,这些可能很有用,因为它将被移动到进位位。