ARM 文档对 PUSH 和 POP 做了如下说明
PUSH 将寄存器存储在堆栈上,编号最小的寄存器 使用最低的内存地址和最高编号的寄存器 使用最高内存地址。
POP 从堆栈中加载寄存器,编号最小的寄存器 使用最低的内存地址和最高编号的寄存器 使用最高内存地址。
我发现一个教程说的是这个
...{} 中的寄存器可以按任意顺序指定,但是 它们在堆栈中出现的顺序是固定的...
所以根据上面的解释,一个PUSH括号中的寄存器的顺序并不重要。 IE。
PUSH {R0,R1,R2}
、PUSH {R2,R1,R0}
和PUSH {R1,R2,R0}
都会导致堆栈中的某些顺序,因为“...最低/最高编号的寄存器(R0/R2)使用最低/最高(堆栈)内存地址。 ..”.
这是否意味着如果单个 PUSH 指令有多个寄存器 支架,装配器自动排序推动动作 out 在目标代码中,其中
PUSH R2
首先进入堆栈
取最高地址,然后是 PUSH R1
,最后是 PUSH R0
取最低地址?
因此,如果我想保证 R2 在 LIFO 堆栈中最后压入并首先弹出(即 SP指向R2或R2取最低堆栈地址),我不能 在一个 PUSH 括号语句中执行此操作,但只能单独使用
PUSH R0; PUSH R1; PUSH R2
?
你已经很接近了,你需要始终获得TRM(核心、cortex-m3、cortex-m0等的技术参考手册)和ARM(该核心armv6-m、armv7-指定的架构的架构参考手册)米,armv8-米)
.thumb
push {r0,r1,r2}
push {r2,r1,r0}
push {r0}
push {r1}
push {r2}
Disassembly of section .text:
00000000 <.text>:
0: b407 push {r0, r1, r2}
2: b407 push {r0, r1, r2}
4: b401 push {r0}
6: b402 push {r1}
8: b404 push {r2}
从ARM ARM中你可以看到push指令的低8位是寄存器列表/掩码。所以 r0 是位 0,r1 是位 1,依此类推。所以b407中的7表示r0,r1,r2这三个寄存器。该逻辑在机器代码而不是汇编语言上运行,机器代码从位 0 到位 7(如果设置),然后压入该寄存器。汇编器所做的只是创建机器代码,它不会创建额外的指令或类似的东西。
如果您希望它们以不同的顺序排列,那么您必须用汇编语言将它们编写在单独的指令中。
寄存器按顺序存储,编号最小的寄存器到最低内存地址(start_address),编号最大的寄存器到最高内存地址(end_address)
起始地址是SP的值减去要存储的寄存器数量的4倍。
后续地址是通过将前一个地址增加 4 来形成的。为 .
中指定的每个寄存器生成一个地址
end_address 值比 SP 的原始值小 4。 SP 寄存器递减 4 倍的寄存器数量 .
如果你查看汇编的十六进制/二进制,你会发现
push
具有相同的寄存器但不同的顺序编码为相同的指令。这与指令编码有关,因为它几乎是寄存器的位掩码(请参阅ARM 汇编器中的寄存器操作数如何编码?)