Assembly 如何在ARM(ARM7TDMI)上最有效地获取低16位半字?

Assembly 如何在ARM(ARM7TDMI)上最有效地获取低16位半字?,assembly,arm,arm7,Assembly,Arm,Arm7,假设寄存器中有一个32位值:r0=0x12345678;任务是获取低位半字部分,即0x5678(或者将高位半字置零)。 就C代码而言,它相当于:r0=r0&0xFFFF 限制:需要在单个ARM7TDMI指令中完成,而不使用其他寄存器。这是因为获得高半拍只是一个右移,如LSR r0,r0,#16 到目前为止,我可以用两种方法来做:左移+右移,旋转+移位;或者使用包含掩码0xFFFF和ing的附加寄存器 在ARM7TDMI上,不可能只使用0xFFFF这样的常量进行AND,因为它不适合立即值方案 此外

假设寄存器中有一个32位值:r0=0x12345678;任务是获取低位半字部分,即0x5678(或者将高位半字置零)。 就C代码而言,它相当于:
r0=r0&0xFFFF

限制:需要在单个ARM7TDMI指令中完成,而不使用其他寄存器。这是因为获得高半拍只是一个右移,如
LSR r0,r0,#16

到目前为止,我可以用两种方法来做:左移+右移,旋转+移位;或者使用包含掩码0xFFFF和ing的附加寄存器

在ARM7TDMI上,不可能只使用0xFFFF这样的常量进行AND,因为它不适合立即值方案

此外,现代ARM-s似乎有“MOVT”,它通过执行
MOVTR0、#0
来解决这个问题,但ARM7TDMI没有


我想相信,没有MOVT,这是可能的,因为这是一件非常基本的事情。

如果有人暗示这可以在ARM7TDMI上的一个指令中完成,那么他们就让你上了。所有早期ARM文档中的规范“零扩展半字”序列是两个移位,如以下示例所示:

4.15.5加载半字(小端) 7TDMI(ARMv4T)在7DI(ARMv3)上添加的是半字加载和存储*,因此这个特定的示例在此之后就消失了(它只是
LDRH-Ra,[Rb]
),但加载当然只针对内存中已经存在的值;在ARMv6引入
UXTH
/
SXTH
之前,在单个指令中仍然没有零/符号扩展寄存器


*在许多其他与此无关的事情中。

如果有人暗示这可以在ARM7TDMI上的一个指令中完成,那么他们就让你上了。所有早期ARM文档中的规范“零扩展半字”序列是两个移位,如以下示例所示:

4.15.5加载半字(小端) 7TDMI(ARMv4T)在7DI(ARMv3)上添加的是半字加载和存储*,因此这个特定的示例在此之后就消失了(它只是
LDRH-Ra,[Rb]
),但加载当然只针对内存中已经存在的值;在ARMv6引入
UXTH
/
SXTH
之前,在单个指令中仍然没有零/符号扩展寄存器


*在许多与此无关的事情中。

什么是上下文;i、 例如,从内存中移动一个立即数、一个寄存器或加载16位半字?另请参见目前的“最有效”。您的目标是像ldrh r0,=0x12345678这样做,其中r0将接收文本池0x12345678的低16位(不要与内存地址混淆)?上下文是32位值已加载到寄存器中。现在,我需要将第一个寄存器的低位16位剪切到第二个(或相同的)寄存器,即以某种方式丢弃上半部分。在本例中:0x1234是垃圾,0x5678是信息部分。在CPU周期和额外内存使用方面效率最高。理想情况下,具有1个CPU周期且无额外内存(无额外寄存器和文字池)。能否将
0x0000FFFF
保存在循环外部设置的另一个寄存器中?上下文是什么;i、 例如,从内存中移动一个立即数、一个寄存器或加载16位半字?另请参见目前的“最有效”。您的目标是像ldrh r0,=0x12345678这样做,其中r0将接收文本池0x12345678的低16位(不要与内存地址混淆)?上下文是32位值已加载到寄存器中。现在,我需要将第一个寄存器的低位16位剪切到第二个(或相同的)寄存器,即以某种方式丢弃上半部分。在本例中:0x1234是垃圾,0x5678是信息部分。在CPU周期和额外内存使用方面效率最高。理想情况下,只有1个CPU周期,没有额外的内存(没有额外的寄存器,也没有文字池)。能否将
0x0000FFFF
保存在循环外部设置的另一个寄存器中?
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