ARM的加载和存储字节和半字指令是如何工作的?有符号和无符号有什么区别?

6
我是一名有用的助手,可以帮您进行翻译。

我刚开始学习ARM技术,但对于负责载荷和存储指令的确切作用感到困惑。

负责载荷的指令:

ldrsb
ldrb
ldrsh
ldrh
ldr

存储指令:

strb
strh
str

“加载半字”有符号或无符号是什么意思?或者“加载字节”有符号或无符号是什么意思?有符号和无符号有什么区别,一些装载/存储指令在哪些特定应用中实用?

总的来说,我希望能直观地理解这些指令的作用,因为我仍然对它们如何工作以及它们的目的感到困惑。

3个回答

13

当谈论ARM时,“字(word)”是32位,“半字(halfword)”是16位,“字节(byte)”是8位。如果您在ARM架构参考手册中阅读指令集文档(如果不知道要获取哪一个,可以使用 infocenter.arm.com 获取ARMv5),您将看到 ldrb 将字节加载到目标寄存器的低8位,填充上方的24位为零。ldrsb 将进行符号扩展而不是填充零位。半字同理。

如果您有如下代码:

char a,b,c;
...
c = a+b;
if(c<0)
{
}
如果在执行加法时,a、b或两者都在内存中,并且您想要进行符号扩展(假设您已告诉编译器char是有符号的),以保存指令符号扩展寄存器,从而可以执行数学运算并正确设置标志进行比较,则最好使用LDRSB(加载有符号字节寄存器)从内存加载一个字节,将其符号扩展为32位字,并将结果写入通用寄存器。而LDRB(加载字节寄存器)则会从内存加载一个字节将其零扩展为32位字,并将结果写入通用寄存器。


你能举个ldrsb的例子吗? - ubuntu_noob
1
你指的例子是什么意思?以 LDR 指令为例,添加 B 后缀就变成了字节传输而非字传输。 - old_timer
@old_timer 为什么没有 strsb 或 strsh 存在? - Savannah Madison
2
@SavannahMadison:符号扩展只有在将较窄的值转换为较宽的值时才有意义,例如将字节转换为字,就像ldrsb所做的那样-您必须决定要放入目标字中的上24位是什么。当将宽值转换为窄值时,只有一种明智的选择:移动源字的低位并忽略高位,这就是strb所做的。 - Nate Eldredge

9
ARM是一种精简指令集(Reduced Instruction Set Computing)架构,这意味着需要使用所提到的指令:加载和存储指令,来将内存移入和移出寄存器。

Load instructions take a single value from memory and write it to a general purpose register. Store instructions read a value from a general purpose register and store it in to memory.

Most Often Used Load/Store Instructions

Loads            Stores      Size and Type
LDR              STR         Word (32 bits)
LDRB             STRB        Byte (8 bits)
LDRH             STRH        Halfword (16 bits)
LDRSB                        Signed byte
LDRSH                        Signed halfword
LDM              STM         Multiple words

(摘自ARM汇编语言-William Hohl)

通常,加载和存储指令的形式如下:

LDR | STR {type}{cond}    Rt, [Rn {, #offset}]

(虽然根据您想要使用的寻址模式有一些差异,但我不会在这里进一步讨论。如果您想了解更多寻址模式的信息,可以查看'ARM后索引和前索引寻址')

'类型'是可选的,并在上面的表格中描述,您可以选择使用半字、字节以及有符号或无符号的字节或半字来工作。您还可以选择加载或存储多个寄存器。

您还可以选择向指令添加条件代码(cond),该代码用于设置当前程序状态寄存器(CPSR)中保存的条件标志 - 如果您想了解更多信息,可以搜索'ARM条件执行''条件代码'

在ARM中,您必须提供源/目标寄存器,同时还必须提供一个包含引用内存位置的地址的寄存器。这是因为ARM指令是固定长度(32位),其中一些位需要用于指令本身,因此不可能在32位ARM指令中封装32位内存地址。

在上面的示例中,'Rt'是您从内存加载的值将落入的寄存器(或者如果您执行存储,则包含要存储到内存中的值的寄存器)。 'Rn'是包含地址的寄存器。括号用于告诉处理器我们正在使用包含地址的寄存器,即我们正在使用指针。可选偏移量存在以防您想要从基本寄存器偏移特定量(这在各种有用的应用程序中非常方便,但我不会在此介绍它们)。

希望这让您了解ARM的加载和存储指令的工作方式! :)


2
当我们使用比一个字更窄的load指令时,我们必须扩展比目标寄存器短的值。因此,ldrh和ldrb必须与ldrsh和ldrsb区分开来,告诉CPU如何“填充”寄存器(零扩展 vs 符号扩展)。
但是当我们使用store指令时,DRAM中的目标存储元素是一个字节或半字,存储值的大小必须是字节的倍数,不需要扩展值以填充目标存储元素。没有选择要存储什么,只需截断即可,即存储低8位或16位,这样可以保留有符号或无符号整数的值(因为ARM是二进制补码机器)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接