【问题标题】:How to load multiple data directly from label to registers如何将多个数据直接从标签加载到寄存器
【发布时间】:2019-10-03 04:37:07
【问题描述】:

我想知道是否有办法将存储在内存中的单词数组加载到寄存器数组中。

我知道 ldm 可用于一次加载多个寄存器,但我的理解是您需要为它提供一个已经保存第一个元素的寄存器。

是否有一些伪指令可以提供帮助?类似 ldm =array, {r0,r1,r2} (仿照实际的伪指令 ldr)。

提前致谢!

【问题讨论】:

  • 在最近的 ARM 上,ldp 加载了一对寄存器。不确定ldm 是否可以使用附近的 PC 相对寻址模式。如果数据距离较远,则无论如何都需要寄存器中的标签地址。您可以只使用要加载的最后一个寄存器作为地址的暂存寄存器。
  • @PeterCordes 我认为ldm 会将源加载到内部加载/存储管道寄存器中,因此可以在目标列表中加载来破坏它。问题在于回写。从内存中加载寄存器 AND 写回结束值有点无意义。但是OP不想要这个。如果某处的某些 ARM 不支持ldm rN, {...,rN},我不会感到惊讶,但它应该可以工作。
  • @artlessnoise:是的,我正在想象使用ldm 没有写回来覆盖地址寄存器。如果可能的话。 (而且由于我在第一条评论中提到了这种可能性,因此 PC 相对 ldm 是不可能的。指令使用指令字中的空间来加载要加载的寄存器的位图,而不是位移。感谢您的提醒ldm 需要寄存器中的指针,而不是普通的 addr 模式。)

标签: assembly arm


【解决方案1】:

见:Getting a label to a register

传统ARM中获取标签的方式有四种,

 target:
     .long 0xfeadbeef, 0xdeadfeed, 0xbaddad00
  1. adr r0,target
  2. adrl r0,target
  3. ldr r0,=target
  4. sub r0,pc,#(.+8-target)

Thumb2 添加了 movw movt 组合,但这不适用于您的用例。

第1,2,4项基本相同。第 3 项将一个地址作为常量添加到 literal pool 中,并将该地址加载到寄存器中。 'C' 之类的东西。

int variable;
const int *p = &variable;
int *reg = p; /* load register from memory */

是否有一些伪指令可以提供帮助?类似 ldm =array, {r0,r1,r2} (仿照实际的伪指令 ldr)。

这里没有伪操作;你必须直接编码。

鉴于上面的“目标”定义具有三个值,您可以使用...

 target:
     .long 0xfeadbeef, 0xdeadfeed, 0xbaddad00
 adr  r0, target
 ldm  r0, {r0-r2}  ; r0 as source/dest should work without write back
                   ; ldm r0, {r1-r3} maybe safer.

伪操作没有实现,因为这是“罕见的”,ldm 是限制性的,不支持将 PC 的偏移量作为源。类似的,

 ; I just thunk it.
 ldm pc, {r0-r2,pc}  ; pc is always '8' ahead, assuming arm mode.
 nop
 .long arg0, arg1, arg2, routine

也许可以,但有限制,因为数据必须与代码一起定位,并且控制流也有限制。同样,这是一个罕见的用例,伪操作是为了更容易将任意常量放入通常需要的寄存器中。所以只有ldm命令的直接编码。某些 ARM CPU/架构可能不支持将相同的寄存器作为目标;绝对不支持回写 (rN!)。这取决于您所针对的 ARM CPU 类别。使用PC 作为源可能更不可能在一大类ARM CPU 上工作。我会推荐第一个示例 (rN != r15),除非您的寄存器用完并且在已知的 SOC/特定 ARM CPU 上。


ldrd 指令是限制性双字加载,但源代码具有更大的灵活性。您可以使用它来加载两个值,而无需单独的adr。例如,

ldr r0, r1, [pc, #offset]

但仅限于两个寄存器。目标寄存器必须是连续的,第一个是 rN,其中N % 2 为零或N 为偶数

【讨论】:

  • ldm 并不是真正的伪操作,而是真正的机器指令。除非你的意思是an alias for ldmia。手册确实说回写是可选的,但也说“Rn 不能是 PC”。 (至少在 Cortex-M3 上,这是谷歌为ldm ldmia 出现的)。但是,如果您指定回写后缀,则 reglist 不得包含 Rn。 这表明 无需 回写您可以安全地覆盖地址寄存器。 (同样,Cortex-M3 的文档)
猜你喜欢
  • 2019-12-04
  • 2021-11-26
  • 1970-01-01
  • 2022-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多