KMC*_*KMC 3 stack arm thumb cortex-m
ARM 文档对 PUSH 和 POP 做了以下说明
PUSH 将寄存器存储在堆栈上,编号最低的寄存器使用最低的内存地址,编号最高的寄存器使用最高的内存地址。
POP 从堆栈中加载寄存器,编号最低的寄存器使用最低的内存地址,编号最高的寄存器使用最高的内存地址。
我发现的一个教程是这么说的
...{} 中的寄存器可以按任意顺序指定,但它们在堆栈中出现的顺序是固定的...
因此,根据上述解释,一个 PUSH 括号中的寄存器顺序并不重要。即PUSH {R0,R1,R2},PUSH {R2,R1,R0}, 和PUSH {R1,R2,R0}所有都会导致堆栈中的某种排序,因为“...最低/最高编号的寄存器(R0/R2)使用最低/最高(堆栈)内存地址...”。
这是否意味着如果单个 PUSH 指令在括号中具有多个寄存器,汇编器会自动在目标代码中对推送操作进行排序,其中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-m、armv8-m)
.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}
Run Code Online (Sandbox Code Playgroud)
在 ARM ARM 中,您可以在推送指令中看到低 8 位是寄存器列表/掩码。所以 r0 是位 0,r1 是位 1,依此类推。所以b407中的7表示r0,r1,r2这三个寄存器。该逻辑在机器代码而不是汇编语言上运行,机器代码从位 7 转到位 0(如果设置),然后压入该寄存器。汇编器所做的只是创建机器代码,它不会创建额外的指令或类似的东西。
如果您希望它们以不同的顺序排列,那么您必须用汇编语言将它们编写在单独的指令中。
寄存器按顺序存储,从编号最低的寄存器到最低内存地址 (start_address),到编号最高的寄存器到最高内存地址 (end_address)
start_address 是 SP 的值减去要存储的寄存器数量的 4 倍。
后续地址是通过将前一个地址增加 4 来形成的。为 中指定的每个寄存器生成一个地址。
end_address值比SP的原始值小四。SP 寄存器按 中寄存器数量的四倍递减。