概述

LDR伪指令可以将一个表达式的值加载到指定寄存器中,区别于汇编指令LDR,汇编指令LDR是加载指定地址的内容到寄存器中。

LDR伪指令的格式:

LDR Rn,=expr

// 举例
LDR R0,=0x12345678

为什么会有LDR这个伪指令

  1. ARM使用了RISC指令集,RISC区别于CISC的一大特点就是指令都是定长的,而CISC不同指令的指令长度可能不一样。

  2. 那么对于使用了RISC指令集的32位处理器,想要在指令中使用一个32位的立即数是不可能的。

  3. 因为这类处理器的指令长度肯定是32位的,32位的空间除了要存储立即数本身还要包括操作码等信息,没有空间容纳32位立即数。

  4. 当然,容纳32位的地址也是不可能的。

  5. ARM提供了一种补救方法,即immed_8r—常数表达式,但依旧不能表示出$2^{32}$个数/地址。

  6. 所以就出现了LDR Rn,=expr这个伪指令,这个伪指令可以将任意一个立即数赋值给寄存器。

实现原理

当立即数/地址可以由immed_8r表示时

这种情况就是直接指令MOV指令完成数据传送即可

源代码:

LDR R0,=0x00000000

生成的汇编码:

MOV R0,#0

当立即数/地址不能由immed_8r表示时

这种情况编译器会在合适的位置分配空间存入要赋值的立即数/地址,然后使用相对寻址的方式来完成数据传送。当然偏移量也必须是能够由immed_8r表示,不过这个不是我们需要关心的,编译器自然会计算出来的。

源代码:

LDR R0,=0x12345678

生成的汇编码:

指令地址:0x08000008 指令内容:LDR.W r0,[pc,#4]
指令地址:0x08000010 指令内容:DCW 0x5678
指令地址:0x08000012 指令内容:DCW 0x1234