如何判断立即数的合法性?(详解详析)
《ARM体系结构与编程》一书中对立即数有这样的描述:每个立即数由一个8位的常数循环右移偶数位得到。
一个32位的常数,只有能够通过上面构造方法得到的才是合法的立即数。
那好,我们便从8位和偶数位这两个角度入手,来去判断立即数的合法性。
(这里,8位数其实可以理解为一种基准,判断立即数合法性这一过程,其实都是建立在对8位数的分析之上。)
书上给的合法立即数的例子:0x104,0xff0,0xff00
我们来分析一下0x104:
(这里我们使用一个小技巧:在刚学习立即数的判断时,非常建议把需要判断的数补全至32位,方便观察与理解)
0x104:0001 0000 0100
补全至32位变成:
0000 0000 0000 0000 0000 0001 0000 0100
这个32位的数我们将之称为 “目标”
现在我们只需要找到一个8位数作为基准,将其补全至32位,如果这个32位数循环右移偶数位之后能够与“目标”相等,那么说明“目标”是一个合法的立即数。
①补全32位的过程中我们发现 ,补全一个数,其实补的全部都是“0”,而32位数里面的“1”,其实都是原先的数自带的,因此我们在找一个8位数作为基准的时候,这个8位数里面一定要包含32位数中所有的“1”,这样我们在对8位数进行循环右移操作的时候才能得到目标数
比如 :0010 永远不可能通过循环右移得到 1100 ,而却能够通过循环右移得到0100 ,因为跟前者的“1”的数目不对应,跟后者的“1”的数目相同
②了解了这一点后,我们现在来找0x104中的含全部“1”的最短序列 ,显然是1 0000 01。这才只有7位,而我们需要8位,因此可以在前后任选一处补一个“0”让它变为8位
(1)1 0000 01前面补一个0得:01 0000 01 ,
补全至32位得:
0000 0000 0000 0000 0000 0000 0100 0001
目标数为:
0000 0000 0000 0000 0000 0001 0000 0100
观察发现8位数补全后的数循环右移30位即可得到目标数,30是偶数,因此成立。故该立即数合法
(2)1 0000 01后面补一个0得:1 0000 010,
补全32位得:
0000 0000 0000 0000 0000 0000 1000 0010
目标数为:
0000 0000 0000 0000 0000 0001 0000 0100
观察发现8位数补全后的数循环右移31位即可得到目标数,31不是偶数,所以1 0000 010没法得到目标数。
③因为两种补0方法的其中一种成立了,我们终归还是找到了一个8位数,它循环右移偶数位能够得到目标数,所以综上:目标数是个合法的立即数
举了上面一个合法立即数的例子,相信你已经大致掌握了判断立即数合法性的方法,其中②补“0”这步,熟练了之后其实是很快的(基本上一眼就行)。有时候比较小的数,需要补的“0”也不止一个,上下对比一下,只要保证循环右移偶数位能得到目标数就行。
来看几个不合法立即数的例子:
0x1010,0x00102,0xFF1000
①0x1010:0001 0000 0001 0000
先找8位数,因为要包含全部“1”,所以最短就是1 0000 0001
这直接就已经9位,溢出了,所以直接pass,不符合8位数的要求
②0x00102:0000 0000 0001 0000 0010
先找8位数,最短是1 0000 001 正好8位,符合条件
把8位数补全至32位 :
0000 0000 0000 0000 0000 0000 1000 0001
目标数(补全到32位)是:
0000 0000 0000 0000 0000 0001 0000 0010
发现8位数补全后的数循环右移31位能得到目标数,因为31不是偶数,而且只有这一种情况,所以也pass了,该立即数不合法。
③0xFF1000
包含所有“1”的最短数都已经12位了,远超8位,直接pass
OK,以上就是所有判断立即数合法性的内容了,讲的较为详细,适合初学者。主要是因为今天在网络上搜索相关内容,感觉都不够通俗易懂,亦或是总结的不够到位,有的甚至还充斥着错误,于是就自己总结一下。如有错误之处还请批评指正,感谢!