因为A32和T32指令都只有32位。因此指令编码能表示的立即数也是有范围限制的。为了表示32位的立即数,你需要多条指令(当然可以用像LDR这样的伪指令进行转化,然后从内存中去拷贝)。
比如为了把32位的立即数加载到寄存器可以用下面几种方法:
- 使用MOV加载低半字的数据,紧接着用MOVT加载高半字的数据到寄存器(用MOV32伪指令也可以达到同样效果)。
- 使用伪指令LDR让编译器替你去自动去选用合适的汇编序列指令把数据加载到寄存器。
当然如果你要加载的立即数是在数据处理类的汇编指令能够处理的范围之内,一条汇编指令就能处理完成。
下面对立即数加载到寄存器进行介绍,主要以MOV/MVN进行说明,其他的一些数据处理汇编指令可能也可以适用,具体可以参考ARM的汇编用户手册:
使用MOV/MVN能一次加载的立即数
在A32中
- MOV可以加载任意8位值的立即数,取值访问0~255(该值可旋转任意偶数位数,该范围的立即数同样适用于其他数据处理汇编指令)
- 这些8位值也可以转换成按位的补码,然后使用MVN进行加载。比如MOV中的值为n,那么要用MVN来加载的话需要用值 -(n+1)来加载。
- MOV可以加载任意16位值的立即数,取值访问0~65535(只适用于MOV,不适用于其他汇编指令)
下表MOV/MVN的8位值有效范围
![](https://img.haomeiwen.com/i9347150/73903b21791cba57.png)
下表MOV的16位值有效范围
![](https://img.haomeiwen.com/i9347150/6f6c8126dd8bfb82.png)
在T32中
T32有32位和16位的指令,先说下16位的,因为比较简单
- 如果是16位的MOV那么能加载的立即数范围仅限于0~255
在说下32位的MOV指令情况
- MOV可以加载任意8位值的立即数,取值访问0~255(该值可左移任意位数)
- 32位的立即数如果符合下面特征也是合法的:
- 每个字节(8位)的值都是一样的,共4字节
- 1,3字节的值为0值,0,2字节的值是一样的
- 0,2字节的值为0值,1,3字节的值是一样的
上面这些情况同样适用于数据处理类的汇编指令
- 同样上面的这些值也可以转换成按位的补码,然后使用MVN进行加载。比如MOV中的值为n,那么要用MVN来加载的话需要用值 -(n+1)来加载。
下表32位的T32指令能加载的立即数
![](https://img.haomeiwen.com/i9347150/e5b3651d01cdbef4.png)
-
MOV可以加载任意16位值的立即数,取值访问0~65535(只适用于MOV,不适用于其他汇编指令),如下表所示:
image.png
那么如何加载超出MOV/MVN能加载范围的值,使用伪指令,下面介绍一下使用LDR加载的方法。
使用下面语法格式的LDR伪指令
LDR Rd,=const
可以加载任意32位的立即数
伪指令的生成过程大致如下:
- 如果加载的值在MOV/MVN有效的范围内则用MOV/MVN进行替代。
- 如果不再MOV/MVN能加载的范围则,把该值放在文字池(literal pool )里面,然后使用LDR指令相对PC寻址的方式,从文字池里面去读取该值,如下例子:
LDR rn, [pc, #offset to literal pool]; rn = *(PC + offset)
备注:使用伪指令需要注意的是汇编器生成的文字池必须在LDR能够寻址的访问之内。那么什么是文字池,简单说就是一块存储常量的存储空间块,该空间块嵌在代码块中的。
参考文献
【1】DUI0801I_armasm_user_guide
网友评论