在 ARM 数据处理指令中, 当参加操作的第二操作数为当即数时, 每个当即数都是选用一个8位的常数循环右移偶数位而直接得到, 其间循环右移的位数有一个4位二进制的2倍一共. 则有用当即数可一共为: := immed_8; 循环右移(2×rotate_imm). 其间: 代表当即数, immed_8 代表8位常数, 即所谓的”8位图”, rotate_imm 代表4位的循环右移值. 这样一来呈现了一个问题: 虽然一共的规模变大了, 可是12位所能体现的数字的个数是必定的. 因而, ARM 规矩并不是一切的32位常数都是合法的当即数, 只需经过上面的结构方法得到的才是合法的当即数, 编译的时分才不会报错. 举个比方吧. 0x3FC(0000 0000 0000 0000 0000 0011 1111 1100) 是由 0xff 循环右移 2 位得到的; 200(0000 0000 0000 0000 0000 0000 1100 1000) 是由 0xc8 循环右移 2 位得到的, 它们都是合法的. 而 0x1FE(0000 0000 0000 0000 0000 0001 1111 1110) 和 511(0000 0000 0000 0000 0000 0001 1111 1111) 无法看成是8位的常数循环右移偶数位而得到的, 因而是不合法的. 指令操作数当即数时分,每个当即数由一个8位的常数循环右移偶数位得到。 = immed_8 循环右移( 2*rotate_imm) 打个比方: 1.当即数0xF200是由0xCF2直接一共的,便是由8位的0xF2循环右移24(2*12)得到的 immed_8 == 0xF2; rotate_imm == 0xC 0000 0000 0000 0000 1111 0010 0000 0000 = = 0000 0000 0000 0000 0000 0000 1111 0010 ->循环右移24位。 2.当即数0x3F0是由0xE3F直接一共的,便是由8位的0x3F循环右移28(2*14)得到的 immed_8 == 0x3F; rotate_imm == 0xE 或许 当即数0x3F0是由0xFFC直接一共的,便是由8位的0xFC循环右移30(2*15)得到的 immed_8 == 0xFC; rotate_imm == 0xF 一共方法有好几种 PS:其实你没必要一个一个的算,只需运用LDR伪指令就能够了,例如:
var script = document_createElement_x_x_x_x_x_x_x(script); script.src = http://static.pay.baidu.com/resource/baichuan/ns.js; document.body.a(script);
ldr r1, =12345678 编译器自然会给你做作业,实际的编程中应该也是这个居多吧 比较下来, 咱们能够这样总结: 1. 判别一个数是否契合8位位图的准则, 首要看这个数的二进制一共中1的个数是否不超越8个. 假如不超越8个, 再看这n个1(n<=8)是否能一起放到8个二进制位中, 假如能够放进去, 再看这八个二进制位是否能够循环右移偶数位得到咱们欲运用的数. 假如能够, 则此数契合8位位图原理, 是合法的当即数. 不然, 不契合. 2. 无法一共的32位数, 只需经过逻辑或算术运算等其它途径获得了. 比方0xffffff00, 能够经过0x000000ff按位取反得到. 因而今后的编程中, 时间查看用到的第二操作数是否契合8位位图是一件千万不能忽略的事. 至于为什么要将这12位 operand2 "八四开", 这个问题就要讨教大牛了.
====持续:为什么是8位+4为右移?
咱们arm指令是固定32位(4字节)的,一共当即数的只需12位,而要表达32位的当即数,就必须用多条指令才行,假如按惯例思路,当即数0xFFFFFFFF则这样表达:
-
Rn = 当即数高12位
-
Rn <<= 12 <--------这儿糟蹋8位当即数空间,由于12=1010
-
Rn |=当即数后12位
-
Rn <<=12 <--------这儿糟蹋8位当即数空间,由于12=1010
-
Rn |=当即数低8位 <--------这儿糟蹋4位当即数空间
这样用5条指令才能将32位的当即数放入Rn寄存器中,而这样占用的内存=20字节,明显整个指令链太长,并且糟蹋bit
位。
而arm的规划正是考虑到了这一点,想出了这个很绕人的解决方法,且没有阐明思路,导致这儿成为了咱们的困惑。下面是我剖析。
-
机器码中当即数呈现得最多的用处是地址,而arm 中要求地址是偶数对齐。(循环右移意味着当2*rotate_imm大于8的时分,得出的当即数总是偶数,这样更有利于一共地址)
-
4位二进制数只能右移动16位,明显不能把当即数8位彻底移动到32位的高24位,所以只好选用先将4位扩展位5位的方法,即*2处理,这样就能够把8位当即数按2粒度移动到32位任一方位,这样咱们只需操控8位的当即数,就可构成恣意32位当即数。
-
arm 用上面的5位直接在其内部按位寻址寄存器相应的位,免去了程序中的位移操作,而价值仅仅编译进程略微杂乱了点。
-
这样最多用4条指令就可完结上面的比方
====持续:ARM汇编编译器依照下面的规矩来生成当即数的编码:
1、当当即数数值爱0和0xFF规模时(8为能够一共的规模),令imme_8=, rotate_imm=0;
2、其他情况下,汇编编译器挑选使rotate_imm数值最小的编码方法。
====添加一点:ARM中应该是运用指令码的25位来判别第二操作数的寻址方法:
第25位(bit[25])为I位,假如I=0,则第2操作数来自一个当即数,假如I=1,则第2操作数来自一个寄存器或移位后的寄存器;