【问题标题】:Difference between commands with [] and without in ARM assemblyARM 程序集中带 [] 和不带 [] 的命令之间的区别
【发布时间】:2025-11-22 20:35:01
【问题描述】:

我注意到在 ARM 汇编中,有 3 种类型(据我所知,可能还有更多)加载/存储命令。到目前为止,我已经看到:

    STR R0, [R1, #4]

    STR R0, [R1], #4

    LDR R0, R1, #4

这些只是我见过的命令的示例。注意最后一个命令是如何加载而不是存储的,那是因为我还没有看到 STR R0、R1、#4,所以我不知道这样写会不会编译。

我知道#4 表示将 R1 增加 4(可能),但与上述命令中的 [] 有什么区别?

【问题讨论】:

  • 从任何基本的 ARM 汇编指南开始或搜索“ARM 寻址模式”或类似内容;已经有 30 年的参考资料了。任何合理的汇编程序都会将第三行视为无效语法而拒绝(因为它是)。
  • Tyvm,将开始搜索。不知道从哪里开始。问题是,我使用了我们大学制造的“自定义”汇编器,我的一位同事写了第三种类型的命令,所以我认为它可以在这个汇编器中编译,但最好不要使用它,因为它会成为一个坏习惯。
  • 方括号基本上是语法糖。加载和存储指令是唯一具有内存操作数的指令,并且它们始终采用内存操作数,因此如果汇编语言没有它们就不会产生歧义。我猜你的汇编程序走捷径,只是忽略了方括号。但是,是的,利用这个“功能”并不是一个好主意。
  • @Ross “如果汇编语言没有它们,就不会有歧义” - 无括号 ldr 预索引或后索引, 然后? ;)
  • @Notlikethat 是的,如果没有方括号,偏移寻址和索引后寻址之间会有歧义。预索引寻址具有 ! 字符,可以消除歧义。

标签: assembly arm addressing-mode


【解决方案1】:

第一个是preindexed:在做操作之前将偏移量加到基数上:

STR r0, [r1, #4]

表示存储在地址r1+0x4完成

请注意,存在预索引 + 回写。此操作将执行相同的存储操作,但基地址将更新为地址。所以最后R1 = R1 + 4

STR r0, [r1, #4]!

另一个是后索引,总是意味着回写:

STR r0, [r1], #4

在这种情况下,存储操作使用地址r1(无偏移),但基址寄存器在存储后更新为R1 = R1 + 0x4

对于某些指令,您可以使用作为寄存器的偏移量,有时还可以使用移位。例如:

STR r0, [r1, r2] ; Store at address r1 + r2
STR r0, [r1, r2 LSL #2] ; Store at address r1 + r2 x 4

并非所有加载/存储指令都可以具有所有寻址模式。

【讨论】:

  • 澄清一下,使用预索引时基址寄存器(例如r1)不会改变,除非调用回写指令。可以通过将! 添加到预索引地址的末尾来完成写回,例如STR r0, [r1, #4]!