ARM汇编:MOV, LDR, LDR伪指令之间区别

在编译ARM汇编时, 用MOV指令编译有时会出错, 但是, 有时又对了, 还有LDR, 有时要加个”=“, 有时又不加了, 非常容易搞混.

1. “8位图”数据

8bit

2. MOV指令

MOV指令可以把立即数或者寄存器内容(注意: 这里绝对不可以是内存!!)传递给一个寄存器. 对于立即数是有要求的, 就是上边的”8位图”数据. 只能由一个8bit连续有效位通过偶数次移位得到的数. 它为什么会有这样的限制呢? 原因是, MOV本身就是一个32bit指令, 除了指令码本身, 他不可能再带一个可以表示32bit的数字, 所以用了其中的12bit来表示立即数, 其中4bit表示移位的尾数(循环右移, 且数值*2), 8bit用来表示要移位的一个基数. 如果立即数超过这个范围, 就没有办法用一条MOV指令给寄存器赋值(这里就要用到LDR伪指令了, 查看反汇编指令, 你会看到LDR伪指令此变成了两条指令~~).

3. LDR指令

首先呢, ldr指令既可以是大范围的地址读取伪指令, 也可以内存访问指令. 当它的第二个参数前面有”=“时, 表示伪指令, 否则表示内存访问指令. LDR指令就是个单寄存器存储的ARM存储器访问指令, 补充了MOV指令不能访问内存的缺陷. ARM是RISC结构的, 数据从内存到CPU之间的移动只能通过ldr/str指令(我说的是单个寄存器~~). 想要把数据从内存中某处读取到寄存器中, 只能用ldr.

4. LDR伪指令

  1. LDR伪指令没有立即数范围的限制, 即可以直接赋值, 因为这是一条伪指令. 如果立即数在MOV的要求内, 系统会自动用一条汇编MOV指令来实现. 如果不在MOV的范围内, 就用其它的方式来实现, 比如变成了两条指令, 或者从PC偏移地址读取一个32位的数据给寄存器.

  2. 关于LDR伪指令, 可以装载一个32bit立即数的说法并不正确, 因为在实际中并不是这一条语句装载了32bit立即数(跟上面的貌似一样, 呵呵~~), 比如:

ldr r1,=0x70000000

其实真正的汇编代码是将某个地址的值传递给r1, 就是说需要一个地址存放0x70000000这个立即数, 在反汇编中, 如果仔细看会发现, 如果这个立即数可以用mov指令的表达形式来表达, 编译器就直接用mov了.

Refs