【问题标题】:Ordering of registers in PUSH and POP bracketsPUSH 和 POP 括号中的寄存器排序
【发布时间】:2020-08-07 15:05:45
【问题描述】:

ARM documentation 对 PUSH 和 POP 表示以下内容

PUSH 将寄存器存储在堆栈中,编号最小的寄存器 使用最低的内存地址和最高编号的寄存器 使用最高的内存地址。

POP 从堆栈中加载寄存器,编号最小的寄存器 使用最低的内存地址和最高编号的寄存器 使用最高的内存地址。

我发现一个tutorial 这么说

...{} 中的寄存器可以按任何顺序指定,但 它们出现在堆栈上的顺序是固定的...

所以根据上面的解释,一个PUSH括号中寄存器的顺序无关紧要。 IE。 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 分开?

【问题讨论】:

    标签: arm stack cortex-m thumb


    【解决方案1】:

    您很接近,您需要始终获取 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}
    

    从 ARM ARM 中,您可以在 push 指令中看到低 8 位是寄存器列表/掩码。所以 r0 是第 0 位,r1 是第 1 位,依此类推。所以 b407 中的 7 表示三个寄存器 r0,r1,r2。该逻辑在机器代码而不是汇编语言上运行,如果设置,机器代码从位 0 到位 7,然后推送该寄存器。汇编器所做的只是创建机器代码,它不会创建额外的指令或类似的东西。

    如果您希望它们以不同的顺序排列,那么您必须用汇编语言在单独的指令中编写它们。

    该逻辑获取列表中启用的寄存器总数,获取堆栈指针,减去 4 个寄存器,然后从该地址开始按列表中的寄存器顺序写入。然后将堆栈指针本身向下调整 4 个寄存器。这一切都记录在 ARM ARM 中。因此,请继续阅读,您会找到问题的答案。

    【讨论】:

      【解决方案2】:
      • 是的
      • 是的

      如果您查看汇编的十六进制/二进制,您会发现 push 具有相同的寄存器但不同的顺序编码为相同的指令。这将与指令编码有关,因为它几乎是寄存器的位掩码(请参阅How are encoded register operands in ARM assembler ?

      【讨论】:

        猜你喜欢
        • 2011-07-29
        • 2018-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-14
        • 2013-04-15
        • 2012-09-12
        相关资源
        最近更新 更多