>假设我们在寄存器中有一个 32 位值:r0 = 0x12345678;任务是获得低半字部分,这是0x5678(或者取消高半字)。 就 C 代码而言,相当于:r0 = r0 & 0xFFFF;
限制:它需要在单个ARM7TDMI指令中完成,而无需使用其他寄存器。这是由于获得高半部分只是像LSR r0, r0, #16
这样的正确转变。
到目前为止,我可以通过 2 个指令来完成:左移 + 右移,旋转 + 移位; 或者通过使用包含掩码0xFFFF和 AND-ing 的附加寄存器。
在ARM7TDMI上,不可能只使用 AND 像 0xFFFF 这样的常量,因为它不适合即时值方案。
此外,看起来现代 ARM-s 有"MOVT",它通过MOVT r0, #0
来解决它,但ARM7TDMI没有!
我想相信没有MOVT是可能的,因为它是如此基本的东西。
如果有人暗示这可以在ARM7TDMI的一个指令中完成,他们就会让你上。所有早期 ARM 文档中的规范"零扩展半字"序列是两个班次,如 ARM7DI 数据表中的此示例所示:
4.15.5 加载半字(小端序)
LDR Ra, [Rb,#2] ; Get halfword to bits 15:0 MOV Ra,Ra,LSL #16 ; move to top MOV Ra,Ra,LSR #16 ; and back to bottom ; use ASR to get sign extended version
7TDMI (ARMv4T) 在 7DI (ARMv3) 上添加的是半字加载和存储*,所以这个特定的例子在那之后消失了(它只是LDRH Ra, [Rb]
),但加载当然只针对内存中已有的值;在 ARMv6 引入UXTH
/SXTH
之前,仍然没有什么可以在单个指令中对寄存器进行零/符号扩展。
* 在许多其他与这里无关的事情中。