如何将 .word 符号加载到 Arm 程序集中的寄存器中?

How to load a .word symbol into a register in Arm assembly?

可能是一个常见的初学者问题,,但我找不到关于几点的任何帮助。如果你有一个用 .word 定义的 32 位符号,你想将它加载到寄存器 r1,那么常规的方法是什么?

.syntax unified
.cpu cortex-m4
.thumb
/* ... */
_allones:  .word 0xffffffff
test:
    /* This seems to not work as expected */
    ldr    r1,_allones   @ Value is corrupted/misaligned?

    /* Two-line solution */
    ldr    r1,=_allones  @ Loads the address of _allones into r1, not the value itself
    ldr    r1,[r1]       @ Get value proper

我的困惑是,当您看到像 this one 这样的教程时,其中只有 ldr r1,=_allones 用于加载 _allonesvalue(请参阅“初始化代码”,第一个列表和解释),以及我在上面链接的答案,这使得我的示例中的第一个选项看起来应该有效。 Target为Cortex-M4,Thumb模式,语法统一

FWIW ldr r1,_allones 行改为加载 _allones 的最后两个字节,然后加载内存中其地址的前两个字节,或者一些徒劳的东西,我没有仔细看在值。

一般来说,ldr r1, =sym会将符号sym的值加载到r1中。 (它通过将 sym 的值组装到内存中一个非常靠近指令的称为文字池的位置来实现,以便可以使用加载指令的 pc-relative 文字形式访问它.)

但是有两种不同的方法来定义符号。它可以被定义为一个标签,如 sym:,在这种情况下,符号的值是它标记的地址(可能直到构建的链接阶段才真正知道)。你的代码就是这种情况。但是符号也可以定义为数字常量,例如 sym EQU 12345,在这种情况下,它的值就是数字 12345。这就是本教程中发生的事情。

所以如果你想把0xffffffff载入r1,两种可能性如下:

allones:
    .word 0xffffffff
...
    ldr r1, =allones @ now r1 contains the address where 0xffffffff is stored
    ldr r1, [r1]     @ load from that address

allones EQU 0xffffffff
...
    ldr r1, =allones

当然,如果实际是0xffffffff,那么最好只写mov r1, 0xffffffff,或者allones equ 0xffffffff ; mov r1, allones。 (# 在一些汇编程序中是可选的。)mov 立即数指令有一组有限的值可以用作立即数,但 0xffffffff 是其中之一。当常数具有适当的值时,某些汇编程序可能会将 ldr r1, =const 优化为 mov r1, const