嵌入式Arm立即数判定

基础知识

在ARM中,机器指令的格式大致有以下几种:
在这里插入图片描述
立即寻址的方式

在这里插入图片描述

立即寻址

  • 在立即寻址,操作数本身直接在指令中给出,取出指令也就获得了操作数,这个操作数也称为立即数。例子如下
ADD R0, R1, #0xF      ;R0=R1+15
MOV R0, #0x55       ;R0=0x55 

在这两个例子中0xF和0x55就是立即数。(立即数要以#开头)

抛出问题

  • 我们知道因为ARM指令长度是32-bit的,所以立即数不可能还有32-bit。
  • ARM在指令格式中设定,只能用指令机器码32位中的低12位来表示要操作的常数。
  • 但是简单的用这12位来表示,显然范围太小了,为了扩展到32-bit,因此使用了构造的方法,在12位中用8位来表示基本数据值,用4位表示移位值,通过用8位基本数据值往右循环移动4位位移值×2次,来表示要操作的常数。
  • 这里要强调终的循环次数是4位位移值乘以2得到的,所以得到的终循环次数肯定是一个偶数,为什么要乘以2呢,实质还是因为范围不够,4位表示位移次数,大才15次,加上8位数据还是不够32位,这样只能通过ALU的内部结构设计将4位位移次数乘以2,这样就能用12位表示32位常数了。

具体点的定义:

立即数 = immed_8 循环右移 (2 * Rotate_imm)
如果存在一个 Rotate_imm 能够让该立即数由 immed_8 循环右移 2×Rotate_imm 位(偶数位)表示,那么这个立即数就是合法的。

那么什么样的立即数才是合法的?

合法立即数的判断

  1. 把数据转化二进制形式,4位一组,不够的补0
  2. 数1的个数,大于8个肯定不是立即数
  3. 如果小于8个,如果数据是两端为1,中间有连续的大于等于24个0,循环左移4的倍数,使高位全为0
    • 比如1111 0000 0000 0000 0000 0000 0000 1111
  4. 找到最高位的1,尽可能多的去掉前面的0(去掉的0必须是偶数个)
    • 比如0001 0010 0010,最高位的1前面有3个0,所以去掉2个0,即××01 0010 0010
  5. 找到最低位的1,尽可能多的去掉后面的0(去掉的0必须是偶数个)
    • 比如0001 0010 0010,最低位的1后面有1个0,所以出掉0个0,即××01 0010 0010
  6. 数剩下的位数,如果小于等于8位,那么这个数就是立即数,反之就不是立即数
举几个例子
(1)0x4FF
  1. 0100 1111 1111
  2. 有9个1,大于8,所以不是立即数
(2)0x122
  1. 0001 0010 0010
  2. 3个1,小于8
  3. 不满足中间有24个0
  4. 最高位的1前面有3个0,所以去掉2个0,即××01 0010 0010
  5. 最低位的1后面又1个0,所以去掉0个0,即××01 0010 0010
  6. 剩下××01 0010 0010共10位,大于8,所以不是立即数
(3)0x234
  1. 0010 0011 0100
  2. 4个1,小于8
  3. 不满足中间有24个0
  4. 最高位的1前面有2个0,所以去掉2个0,即××10 0011 0100
  5. 最低为的1后面又2个0,所以去掉2个0,即××10 0011 01××
  6. 剩下的共8位,等于8,是立即数
(4)0xF000000F
  1. 1111 0000 0000 0000 0000 0000 0000 1111
  2. 8个1,不大于8
  3. 满足中间有24个0,循环左移4位,使高位全为0,即0000 0000 0000 0000 0000 0000 1111 1111
  4. 最高位的1前面有24个0,所以去掉24个0,即×××× ×××× ×××× ×××× ×××× ×××× 1111 1111
  5. 最低为的1后面没有0
  6. 剩下的共8位,是立即数
(5)0x8000007F
  1. 1000 0000 0000 0000 0000 0000 0111 1111
  2. 8个1,不大于8
  3. 满足中间有24个0,循环左移4位,是高位全为0,即0000 0000 0000 0000 0000 0000 0111 1111 1000
  4. 最高位的1前面有24个0,所以去掉24个0,即xxxx xxxx xxxx xxxx xxxx xxxx 0111 1111 1000
  5. 最低为的1后面有3个0,所以去掉2个0,即xxxx xxxx xxxx xxxx xxxx xxxx 0111 1111 10xx
  6. 剩下的共10位,大于8,不是立即数

如何规避立即数

  • 可以通过使用 LDR 伪指令代替
    • 例如直接把MOV指令变为, LDR R1,=0x12345678这样编译器就不会报错。

适合自己的方法才是最好了,真正理解了才能叫懂了!

  • 可以通过使用 LDR 伪指令代替
    • 例如直接把MOV指令变为, LDR R1,=0x12345678这样编译器就不会报错。

总结

适合自己的方法才是最好了,真正理解了才能叫懂了!

才疏学浅,望雅正!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值