ARM 立即数

/*
 * 2018/12/20    11:43    qing
 */

/*
 * ARM中的MOV指令格式
 */

    31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
    |   Cond   | 0 0 | L| OpCode    | S |   Rn     |  Rd       |       Operand2                   |


    op2是占了12位,其中 bit 11 - bit 8 是移位数(rotate), bit 7 - 0 是一个 8 位的立即数(imm),
    
    mov    Rn, op2        @ 执行之后 Rn = op2 >> (rotate * 2),这里的移位是循环右移,这就决定了mov指令不是所有的立即数都能表示的


    1. mov r3, #0x56000000

        虽然0x56000000是一个32位的数,但是可以找到这么一个8位立即数,通过右移得到,看下机器码 e3a03456 ,展开成二进制,对照下格式

        31       27    23     19     15     11     7      3
        1110  0011  1010  0000  0011  0100  0101  0110

        Cond[31:28] = 1110

        [27:26] = 00

        L[25] = 1 ,代表op2是一个立即数

        OpCode[24:21] = 1101

        S[20] = 0

        Rn[19:16]= 0000

        Rd[15:12]= 0011 , R3

        Op2[11:8]= 0100 ,右移 4 * 2 位

        Op2[7:0] = 0101 0110 , 8 位立即数, 0x56        

        首先要将 0x56 扩展成32位的无符号数, 0x00000056 ,然后循环右移 8 位,就得到了 0x56000000


    2. mov r3, #0x56000014

        0x56000014是无法通过移位来得到的,这时编译器会报错,C语言编写的程序,编译器会这样来处理:

        mov r3, #0x56000000

        add r3, r3, #0x14        

        代替mov的另外一条指令就是ldr,或许会更方便点。

    

/*
 * 在ARM中使用立即数的规律
 */

    在ARM中不能像X86那样直接将立即数加载到寄存器中。因为你使用的立即数是受限的。

    可以通过LDR绕过这些限制,有以下的的技巧:


    每条ARM指令的宽度是32位,所有的指令都是可以条件执行的。
    
    有16中条件可以使用而且每个条件在机器码中的占位都是4位。之后我们需要2位来做为目的寄存器。2位作为第一操作寄存器,
    
    1位用作设置状态的标记位,再加上比如操作码(opcode)这些的占位。最后每条指令留给我们存放立即数的空间只有12位宽。也就是4096个不同的值。


    这也就意味着ARM在使用MOV指令时所能操作的立即数值范围是有限的。那如果很大的话,只能拆分成多个部分外加移位操作拼接了。

    所以这剩下的12位可以再次划分,8位用作加载0-255中的任意值,4位用作对这个值做0~30位的循环右移。
    
    这也就意味着这个立即数可以通过这个公式得到:v = n ror 2 * r。换句话说,有效的立即数都可以通过循环右移来得到。
    
    
    这里有一个例子

    有效值:

    #256        // 1 循环右移 24位 --> 256
    #384        // 6 循环右移 26位 --> 384
    #484        // 121 循环右移 30位 --> 484
    #16384      // 1 循环右移 18位 --> 16384
    #2030043136 // 121 循环右移 8位 --> 2030043136
    #0x06000000 // 6 循环右移 8位 --> 100663296 (十六进制值0x06000000)

    Invalid values:

    #370        // 185 循环右移 31位 --> 31不在范围内 (0 – 30)
    #511        // 1 1111 1111 --> 比特模型不符合
    #0x06010000 // 1 1000 0001.. --> 比特模型不符合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值