您的位置 首页 测评

arm汇编当即数有效位数判别

在ARM处理器的汇编语言中,对指令语法格式中的shifter_operand>的常数表达式有这样的规定:该常数必须对应8位位图,即常数是由一个8位的常…

在ARM处理器的汇编语言中,对指令语法格局中的的常数表达式有这样的规则:“该常数有必要对应8位位图,即常数是由一个8位的常数循环移位偶数位得到的。”

首要从ARM指令系统的语法格局说起。

一条ARM指令语法格局分为如下几个部分:

{}{S} ,{,}

其间,<>内的项是有必要的,{}内的项是可选的,如是指令助记符,是有必要的,而{}为指令履行条件,是可选的,假如不写则运用默许条件AL(无条件履行)。

Opcode指令助记符,如LDR,STR

Cond履行条件,如EQ,NE

S是否影响CPSR寄存器的值,书写时影响CPSR,不然不影响

Rd方针寄存器

Rn第一个操作数的寄存器

shifter_operand第二个操作数

其指令编码格局如下:

31-28

27-25

24-21

20

19-16

15-12

11-0(12位)

cond

001

opcode

S

Rn

Rd

shifter_operand

当第2 个操作数的方式为:#immed_8r常数表达式时“该常数有必要对应8位位图,即常数是由一个8位的常数循环移位偶数位得到的。”

其意思是这样:

#immed_8r在芯片处理时表明一个32位数,可是它是由一个8位数(比方:01011010,即0x5A)经过循环移位偶数位得到(1000 0000 0000 0000 0000 0000 0001 0110,便是0x5A经过循环右移2位(偶数位)的到的)。

而1010 0000 0000 0000 0000 0000 0001 0110,就不契合这样的规则,编译时必定犯错。由于你或许经过将1011 0101循环右移位得到它,可是不或许经过循环移位偶数位得到。1011 0000 0000 0000 0000 0000 0001 0110,也不契合这样的规则,很明显:1 0110 1011 有9位。

为什么要有这样的规则?

要从指令编码格局来解说(这便是我为什么一开始讲的是指令编码格局),仔细看表格中的shifter_operand所占的位数:12位。要用一个12位的编码来表明恣意的32位数是肯定不或许的(12位数有2^12种或许,而32位数有2^32种)。

可是又要用12位的编码来表明32位数,怎么办?

只需在表明数的数量上做约束。经过编码来完成用12位的编码来表明32位数。

在12位的shifter_operand中:8位存数据,4位存移位的次数。

8位存数据:解说了“该常数有必要对应8位位图”。

4位存移位的次数:解说了为什么只能移偶数位。4位只需16种或许值,而32位数能够循环移位32次(32种或许),那就只好约束:只能移偶数位(两位两位地移,如同一个16位数在移位,16种移位或许)。这样就处理了能表明的状况是实际状况一半的对立。

所以对#immed_8r常数表达式的约束是处理指令编码的第二个操作数位数不足以表明32位操作数的无法之举,但在我看来:这个能够说是聪明的做法。由于假如直接用12位数来表明32位操作数,只能表明0 到(2^12-1)。大于(2^12-1)的数就没办法表明了。并且细细想来“8位存数据,4位存移位的次数”,应该是最好的组合了(我并未想过一切的组合,仅仅趁便试了几个)。

ARM指令第二操作数#immed_8r详解

大多数ARM通用数据处理指令有一个灵敏的第2操作数(flexible second operand),这儿这解说一下其间的一种格局,#immed_8r常量的表达式。常量有必要对应于8位位图(pattern)。该位图在32位字中,被循环移位偶数位(0,2,4,…28,30)。合法常量0xff,0xff000,0xf000000f。不合法常量:0x101,0xff04

ARM 在32位形式下,一条指令长度为32位,在上述数据处理指令中,操作数2为12位。所以像0x7f02这样的数,要两条指令才干完结。

MOVR3, #0x7F00;E3 A0 3C 7F 该指令自己完结0x7f移位

ORRR1, R3, #2

所以直接是找不到0x7f02的

关于循环移位,其实arm中只需循环右移(ROR)。0x7f到0x7f00是经过循环右移24次才完成的,这儿每次移动2位所以是12次(0xc)

在 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

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伪指令就能够了,例如:
ldr r1, =12345678
编译器自然会给你做作业,实际的编程中应该也是这个居多吧

比较下来, 咱们能够这样总结:

  1. 判别一个数是否契合8位位图的准则, 首要看这个数的二进制表明中1的个数是否不超越8个.假如不超越8个, 再看这n个1(n<=8)是否能一起放到8个二进制位中, 假如能够放进去, 再看这八个二进制位是否能够循环右移偶数位得到咱们欲运用的数. 假如能够, 则此数契合8位位图原理, 是合法的当即数. 不然, 不契合.
  2. 无法表明的32位数, 只需经过逻辑或算术运算等其它途径获得了. 比方0xffffff00, 能够经过0x000000ff按位取反得到.

因而今后的编程中, 时间查看用到的第二操作数是否契合8位位图是一件千万不能忽略的事. 至于为什么要将这12位operand2“八四开”, 这个问题就要讨教大牛了.

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ceping/262724.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部