为什么 ARM LSL 与 LSR 的允许移位值范围不同?

Vig*_*yak 5 assembly arm instruction-set cpu-architecture

为什么LSL 的允许移位值为[0, 31],LSR 的允许移位值为[1, 32]?

LSL 中的 0 位移位对任何应用有何用处?为什么LSR不允许0移?为什么 LSL 不允许 32 位移位?

fuz*_*fuz 3

此限制适用于按立即数进行的轮班。通过寄存器进行的移位不受此类限制。

\n

LSL允许加 0 来指示 \xe2\x80\x9c 没有移位。\xe2\x80\x9d 这是一种特殊情况,因为C标志设置指令的标志未被修改。

\n

LSRASR0 的行为与 0 的行为相同LSL,因此 CPU 设计者决定让立即数操作数 0 表示移位 32,从而实现附加功能。对于 的情况ROR,移位 0 相反表示特殊的 \xe2\x80\x9crotate 右扩展\xe2\x80\x9d 指令,RRX因为旋转 32 不是很有用。

\n

例如,请参阅 ARM7TDMI 数据表,其中显示:

\n
\n

注意LSL #0 是一种特殊情况,其中移位器执行是​​ CPSR C 标志的旧值。Rm 的内容直接用作第二个操作数。

\n
\n
\n

可能预期对应于LSR#0的移位字段的形式用于对LSR#32进行编码,其具有零结果,其中Rm的位31作为进位输出。逻辑右移零是多余的,因为它与逻辑左移零相同,因此汇编器会将 LSR #0(以及 ASR #0 和 ROR #0)转换为 LSL #0,并允许指定 LSR #32。

\n
\n
\n

可能期望给出ASR#0的移位字段的形式用于编码ASR#32。Rm 的第 31 位再次用作进位输出,操作数 2 的每一位也等于 Rm 的第 31 位。因此,根据 Rm 位 31 的值,结果是全 1 或全 0。

\n
\n
\n

可能期望给出ROR#0的移位字段的形式用于编码桶形移位器的特殊功能,即旋转右扩展(RRX)。这是通过将 CPSR C 标志附加到 Rm [...] 内容的最高有效端而形成的 33 位量的右移一位位置。

\n
\n

在 Thumb (T32) 模式中,对约定进行了调整。Thumb 缺乏明确的MOVS Rd, Rn指令,因此LSLS Rd, Rn, #0用于此目的。 LSR Rd, Rn, #imm5ASR Rd, Rn, #imm5行为方式与 A32 模式下的行为相同。#32通过将五位立即数字段设置为零来编码立即数。假设的指令ROR Rd, Rn, #imm5不存在,因为它所在的操作码空间用于编码

\n
ADDS Rd, Rn, Rm\nSUBS Rd, Rn, Rm\nADDS Rd, Rn, #imm3\nSUBS Rd, Rn, #imm3\n
Run Code Online (Sandbox Code Playgroud)\n

反而。

\n

  • *Thumb 缺少独特的 MOVS Rd、Rn 指令* - 它与 ARM 模式并没有完全不同。在 ARM 模式下,“lsl”只是具有非零移位计数的“mov”。这只是一个问题,哪个是“基本”操作,哪个是它/伪指令的应用。我想在 ARM 模式下,说 MOV 是基本指令是最有意义的,而 `lsl r0, r1, #12` 是 `mov r0, r1, lsl #12` 的别名,但在 Thumb 模式指令中则不然*总是*有空间来编码移位的源操作数,所以将“lsls”称为一流的助记符/操作码是有意义的。 (3认同)