arm汇编立即数有效位数判断

发布者:Alisallll最新更新时间:2016-04-20 来源: eefocus关键字:arm汇编  立即数  有效位数 手机看文章 扫描二维码
随时随地手机看文章
在ARM处理器的汇编语言中,对指令语法格式中的的常数表达式有这样的规定:“该常数必须对应8位位图,即常数是由一个8位的常数循环移位偶数位得到的。”

首先从ARM指令系统的语法格式说起。

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

{}{S} ,{,}

其中,<>内的项是必须的,{}内的项是可选的,如是指令助记符,是必须的,而{}为指令执行条件,是可选的,如果不写则使用默认条件AL(无条件执行)。

Opcode   指令助记符,如LDR,STR 

Cond       执行条件,如EQ,NE 

                 是否影响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这样的数,要两条指令才能完成。

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

ORR     R1, 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 "八四开", 这个问题就要请教大牛了.


关键字:arm汇编  立即数  有效位数 引用地址:arm汇编立即数有效位数判断

上一篇:ARM和VC之间进行音频通信
下一篇:ARM,DSP,FPGA,CPLD,SOPC,SOC之间有什么区别和联系

推荐阅读最新更新时间:2024-03-16 14:51

ARM汇编中LDR伪指令和LDR指令
ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。比如想把数据从内存中某处读取到寄存器中,只能使用ldr比如: view plain copy print ? ldr r0, 0x12345678 就是把0x12345678这个地址中的值存放到r0中。而mov不能实现这个功能,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个和x86这种CISC架构的芯片区别最大的地方。x86中没有ldr这种指令,因为x86的mov指令可以将数据从内存中移动到寄存器中。 另外还有一个就是ldr伪指令,虽然ldr伪指令
[单片机]
ARM汇编特殊符号 汇编符号引用
特殊符号 ---- 对应指令 ---- 含义 ---- 示例 ^ ---- MAP ---- 定义结构化内存表 ---- MAP 4096;内存表首地址为4096 # ---- FIELD ---- 定义内存表中的数据,结合MAP指令使用 ---- MAP 4096 STACKSVC FIELD 256;定义从4096开始的256字节为SVC的堆栈空间。 % ---- SPACE ---- 分配一块内存,并用 0 初始化 ---- DataStruc SPACE 280;分配280字节内存并初始化 ---- IF ELSE ENDIF ---- 条件编译,有选择的确定需要编译的代码IF,ELSE,ENDIF,可以嵌套
[单片机]
GNU ARM汇编(四)中断汇编之非嵌套中断处理
在写这篇blog之前,不得不感慨一句:纸上得来终觉浅,绝知此事要躬行.作为EE出身的,虽然好久好久没用汇编写单片机的中断了,但自我感觉对中断的理解还是比较深入的,本以为在GNU ARM汇编下搞个中断会很容易,谁知道断断续续花了我几周.完全用汇编写中断和用c中的_irq写中断还是有区别的,谁用谁知道.还是那句话:深入细节是必须的,也是值得的.         这一篇blog的理论知识主要来源于:《ARM System Developer's Guide》.         ARM的异常和相应的模式之间的对应关系见下表:   当一个异常导致模式的改变时,内核自动地: 1、把cpsr保存到相应模式下的spsr 2、
[单片机]
ARM立即讲解--LDR和MOV的区别
Mov 是把立即数赋给一个寄存器,但对立即数的范围有要求。只能是由8bit连续有效位通过偶数次移位能得到的数。如果立即数超出这个范围,就没办法用一条MOV指令给寄存器赋值。 LDR除了普通的读数之外,也有给寄存器赋立即数的功能。 你只要写 LDR R0,=0xabcdef 它没有立即数范围的限制。因为这是一条伪指令。如果立即数在MOV的要求内,那就用一条汇编来实现。如果不在Mov的范围内,就用其它方式实现,如变成两条指令,或从PC偏移地址读一个32位数给寄存器。 MOV是从一个寄存器或者移位的寄存器或者立即数的值传递到另外一个寄存器 从本质上是寄存器到寄存器的传递,为什么会有立即数,其实也是有限制的立即数,不是所有立即数都可以
[单片机]
arm汇编语言调用C函数之参数传递
对于ARM体系来说,不同语言撰写的函数之间相互调用(mix calls)遵循的是 ATPCS(ARM-Thumb Procedure Call Standard),ATPCS主要是定义了函数呼叫时参数的传递规则以及如何从函数返回,关于ATPCS的详细内容可以查看ADS1.2 Online Books Developer Guide的2.1节。这篇文档要讲的是 汇编代码中对C函数调用时如何进行参数的传递以及如何从C函数正确返回。 不同于x86的参数传递规则,ATPCS建议函数的形参不超过4个,如果形参个数少于或等于4,则形参由R0,R1,R2,R3四个寄存器进行传递;若形参个数大于4,大于4的部分必须通过堆栈进行传递。 我们
[单片机]
ARM汇编指令调试方法
学习ARM汇编时,少不了对ARM汇编指令的调试。作为支持多语言的调试器,gdb自然是较好的选择。调试器工作时,一般通过修改代码段的内容构造trap软中断指令,实现程序的暂停和程序执行状态的监控。为了在x86平台上执行ARM指令,可以使用qemu模拟器执行ARM汇编指令。 一、准备ARM汇编程序 首先,我们构造一段简单的ARM汇编程序作为测试代码main.s。 .globl _start _start: mov R0,#0 swi 0x00901 以上汇编指令完成了0号系统调用exit的调用。mov指令将系统调用号传入寄存器R0,然后使用0x00901软中断陷入系统调用。 为了运行ARM汇编代码,需要使用交叉编译器ar
[单片机]
ARM汇编中的LDR指令总结
ldr只能在当前PC的4KB范围内跳转 B只能在当前PC的32M范围内跳转 label标号实际上就是个地址 eg: 合法: ldr r1, ldr r1, ;不能超过0xfff,否侧编译不能通过或者linker时有错 ldr r1, ;所以这个经常是编译不能通过,因为label的值一般都大于0xfff ldr r1, ,#0x4 ldr r1,label ;把label这个地址里面的内容赋给r1 ldr伪指令 ldr r1,=0x2000014 ldr r1,=label ;把label这个地址值赋给r1 ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完
[单片机]
ARM汇编中ldr与adr的区别
ldr r0, _start adr r0, _start ldr r0, =_start nop mov pc, lr _start: nop 编译的时候设置 RO 为 0x0c008000 0c008000 _start-0x14 : c008000: e59f000c ldr r0, ; c008014 _start c008004: e28f0008 add r0, pc, #8 ; 0x8 c008008
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved