我在 ARMv5 程序集中找到了这样的指令:
pop {r2} ; (str r2, [sp, #-4]!)
push {r0} ; (str r0, [sp, #-4]!)
push {r4, r5, r6, r7, r8, r9, sl, lr}
Run Code Online (Sandbox Code Playgroud)
我知道 push 和 pop 是STR
and的缩写LDR
,并且这些指令存储和加载到多个寄存器,因此我相信这种情况下的大括号意味着“用于存储或加载的寄存器的集合”
我的假设正确吗?
是的,只需阅读指令集文档即可。汇编器可以选择使用 str/ldr 或 stm/ldm 来进行单寄存器压入和弹出操作。如今,您希望保持堆栈在 64 位边界上对齐,因此通常会压入或弹出偶数个寄存器,但如果需要,您可以一次执行一个。对于拇指推/弹出是它们自己的指令,而不是加载或存储的编码。
00000000 <.text>:
0: e49d2004 pop {r2} ; (ldr r2, [sp], #4)
4: e52d0004 push {r0} ; (str r0, [sp, #-4]!)
8: e92d40f0 push {r4, r5, r6, r7, lr}
00000000 <.text>:
0: bc04 pop {r2}
2: b401 push {r0}
4: b5f0 push {r4, r5, r6, r7, lr}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,ARM 编码确实似乎是加载/存储的,而不仅仅是反汇编程序注释 (x4xxxxxx) ldm/stm 是一种 x8xxxxxx 编码,就像上一个编码一样。
当然,所有这些都在这些 ARM 文档中,它们回答了这个问题以及您可能遇到的其他问题。当然,如果每个答案都能被找出来,那么 stackoverflow 可能毫无用处。但在这种情况下,您正在检查一些显示语法的参考,该参考应该有一些额外的文本显示寄存器列表是一个集合。编码分别有 15 位或 9 位,通过一些简单的示例,您可以看到编码与您在语法中指定的列表相匹配。
是的,花括号意味着将它们全部推入或弹出全部,视情况而定。该文档还介绍了设置后递增之前的递减以及哪些寄存器以什么顺序放入内存中。
push {r2,r3,r4}
Run Code Online (Sandbox Code Playgroud)
不同于
push {r4,r2,r3}
Run Code Online (Sandbox Code Playgroud)
例如
另请注意,最初没有推送/弹出指令,它们附带了真正的推送/弹出拇指指令,这些指令不是 ldm/stm(因为它们没有足够的位来刻录 r13,该指令被指定为 16 位中的 4 位,ldm/他们拥有的 stm 仅限于 r0-r7)。同样,您必须为三个寄存器操作指定所有三个寄存器,然后汇编器让您偷懒,让您对arm指令使用拇指语法,然后最终使用统一语法,这只会使事情变得更加复杂而不是更少。
最重要的是请记住,汇编语言通常不是标准化的。它们仅由您正在使用的读取文本的程序的特定汇编器定义,有人可以轻松允许这样做
push (r1,r2)
pop [r3,r4]
push r2,r3,r4,r5
str r3,r2
Run Code Online (Sandbox Code Playgroud)
作为其汇编程序中的合法语法。只要看看相同指令集的arm工具和gnu工具之间的差异就可以了。与传统的 pdp-11 语法相比,pdp-11 gnu 汇编器语法更有趣。(是的,有一个维护的 pdp-11 后端)。
因此,您的问题应该更具体地说明您使用的汇编器,即使我们几乎知道您在问什么。