如何判断合法的立即数

立即数的定义:

    每个立即数由一个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


     








                             

          

你可能感兴趣的:(如何判断合法的立即数)