ARM汇编中是否有小型寄存器?

4

我最近开始学习ARM汇编,发现我只能将32位的值移动到寄存器中,但如果我想像在x86汇编中一样只将8或16位的值移动到寄存器中怎么办。 例如:

arm
eor r0, r0
mov r0, #128

x86
xor eax, eax
mov al, 0x80

r0现在包含了0x80,但它是一个32位的寄存器,因此它将包含0x00000080。

如果这是x86架构,我可以使用al(8位寄存器)来操作最后一个字节,而不是eax(32位寄存器)。

简而言之,ARM汇编中是否有小型寄存器?


1
你有关于ARM汇编的文档吗?如果要仅更改低x位,则需要使用AND将它们清除,然后使用OR进行设置。 - Jongware
RISC架构几乎总是在整个寄存器上运行。没有办法只操作寄存器的一小部分。 - phuclv
那个x86代码相对于5字节的mov eax, 0x80可以节省1个字节的代码大小,但这并不值得。编译器会使用mov eax, 0x80,因为运行一个单一uop指令比运行两个更有效率,即使它多花费了一个字节的代码大小。一个更好的例子是像shl al, 4这样实现(uint8_t) (x<<4),而不是将位移位超过EAX的高位。 - Peter Cordes
2个回答

8

ARM寄存器都是32位的1

然而,假设您使用的是最新的架构版本(ARMv6T2或更高版本),则可以使用BFIUBFX指令从/到另一个寄存器底部插入/提取任意切片,而不影响其他位。对于使用立即操作数来做同样的事情稍微有些棘手,因为MOV会将立即值零扩展2(即您示例中的eor r0,r0完全是多余的)- 您要么必须像上面提到的那样使用ANDORR,要么使用一个中间寄存器进行MOV,然后再跟上BFI


[1] 当考虑AArch64状态时,“固定大小”更为适当 - 在那里,您具有相同寄存器的32位和64位视图,但对32位视图的任何写入都会隐式地将上32位清零,因此仍然适用相同的原则(即它不允许您假装拥有两倍大小的寄存器,就像8086一样)。

[2] MOVT是一个例外,它将立即值加载到寄存器的上16位而不触及下半部分(以允许使用MOVW/MOVT对加载完整的32位立即值)。


3
arm
eor r0, r0
mov r0, #128

为什么不采用以下方法:
mov r0,#128

没有理由使用eor...

您不具备与ARM相同的8位历史,因此寄存器从一开始就是32位。但您仍然有许多指令可以帮助您对寄存器执行低于32位的操作。


我觉得异或运算是无意义的,因为整个32位都被修改了,但我还是保留它,因为对称性很漂亮... - tozhan
明白了,你也可以在x86中使用32位立即数,并提供另一个示例,因为你的示例尝试修改整个32/64位寄存器而不仅仅是8位。 - old_timer

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