立即数的定义:
每个立即数由一个8位的常数循环右移偶数位得到,其中循环右移的位数由一个4位二进制的两倍表示。如果立即数记为<immediate>, 8位常数记为immed_8, 4位的循环右移值记作rotate_imm, 则有: <immediate>=immed_8循环右移(2*rotate_imm)
这样并不是每一个32位的常数都是合法的立即数,只有能够通过上述构造方法得到的才是合法的立即数,下面的常数是合法的立即数:
0Xff,0X104,0Xff0,0Xff00
而下面的常数不是合法的立即数:
0X101,0X102,0Xff1
同时按照上面的构造方法,一个合法的立即数可能有多种编码方式,如0X3f0是一个合法的立即数,它可以采用下面的两种编码方式:
immed_8=0X3f,rotate_imm=0xe 或者
immed_8=0Xfc,rotate_imm=0xf
但是,由于这种立即数的构造方法包含了循环右移操作,这将会影响CPSR的C位,因此,同一个合法的立即数采用了不同的编码方式,将会使某些指令的执行产生不同的结果,这是不允许的,ARM汇编编译器按照下面的规则来产生立即数的编码:
1:当立即数数值在 0 和 0Xff 范围时,令 immed_8=<immediate>,rotate_imm=0
2:其他情况下,汇编编译器选择使rotate_imm数值选择最小的编码方式。
下面给出两条判断依据,判断一个立即数是否合法:
1:首先把这个数用二进制表示出来,然后看这个数中“1”的最大间隔是多少。要看两次,一次是顺序看,一次是循环看,循环看就是把16位或32位寄存器的首尾连起来,越过首尾来看,两次中如果最大间隔都大于8(包含首尾的两个1),那这个数肯定是非法的。如果有一次小于或等于8则有可能是合法的,可以进行下一步的判断。
2:此时又分为两种可能:
a:如果顺序看时“1”的最大间隔小于或等于8,此时可以看看,这个数的最高位1的前面或者最低位1的后面是否有偶数个0,只要有一种情况下有,这个数是合法的的立即数。
b:如果循环看时1的最大间隔小于或等于8,此时可以看看,循环看时,两端得到的间隔个数是否有一个为偶数,如果有一个为偶数,这个数就是合法的。
举例:
以下都是合法的
0xff=0000 0000 0000 0000 0000 0000 1111 1111B,首尾的两个1不大于8,符合2(a),是立即数
0x104=0000 0000 0000 0000 0000 0001 0000 0100B,首尾的两个1不大于8,符合2(a),是立即数
0xff0=0000 0000 0000 0000 0000 1111 1111 0000B,首尾的两个1不大于8,符合2(a),是立即数
0xf000000f=1111 0000 0000 0000 0000 0000 0000 1111B