LDM 指令,STM 指令

(LDM|STM)<cond> [<addressing_mode>] <Rn>[!], ({<Rn>[,<Rn>]}|{<Rn>-<Rn>})
例如
    LDMIA R0,  {R1, R2, R3}
    LDMIA R0,  {R1-R3}
    LDMIA R0!, {R1-R3}  # ! 表示最后那个寄存器的值会改变
  • 多寄存器加载存储指令
格式 地址变化方式 操作寄存器的方向
IA(Increment After) 先存储后增长 –>
IB(Increment Before) 先增长后存储 –>
DA(Decrement After) 先存储后递减 <–
DB(Decrement Before) 先递减后存储 <–

地址改变的时机只与 A,B 有关
地址改变的方向与 I,D 有关,与 LDM,STM 无关
操作寄存器方向上的不同,刚好让内存顺序和寄存器顺序对应匹配起来了。

  • 堆栈寻址方式
格式 地址变化方式 操作寄存器的方向
EA 空栈递增(先存取后改变地址) –>
FA 满栈递增(先改变地址后存取) –>
ED 空栈递减(先存取后改变地址) <–
FD 满栈递减(先改变地址后存取) <–

地址改变的时机只与 E,F 有关
地址改变的方向不仅 与 A,D 有关, 还与 LDM,STM 有关。A 本意是递增,但只有在和 STM 搭配时才是本意。也就是说 STMFA 地址是递增,而 LDMFA 地址是递减的。看似奇怪,换个角度看, FA 是对一个栈的描述。对于同一个栈,压栈和出栈的地址改变顺序必然是相反的。这里仅用了压栈(STM)的顺序来代表这个栈,所以对于出栈(LDM)方向就相反了。
操作寄存器的方向的不同,也是刚好让内存顺序和寄存器顺序对应匹配起来了。

  • 总结

对于LDM 指令,STM 指令,无非就是关系三个指标——什么时候改变地址、往哪个方向改变地址、先操作哪个寄存器。什么时候改变地址,先操作哪个寄存器是相对容易的,复杂在地址改变的方向。判断地址改变方向分两种情况,一种是只看 I,D,一种是通过压栈的方向 A,D 确定一个栈,在这个栈的基础上判断 LDM,STM 的方向。

参考资料

  1. yang_qin224. ARM 汇编指令. 2019-06-20 07:42:06.
  2. 何有飞. LDMIA、LDMIB、LDMDB、LDMDA、STMIA、LDMFD、LDMFA、LDMED、LDMEA等指令详解. 2019-06-20 08:43:20.