https://blog.csdn.net/carlyll/article/details/49209651
参考文章一:
arm指令一般编码格式和一般语法格式
1、编码格式:
2、语法格式:
3、解释:
3.1、<>内的项是必须的,{}内的项是可选的
3.2、opcode:指令助记符;cond:执行条件;S:是否影响CPSR寄存器的值;Rd:目标寄存器;Rn:第1个操作数的寄存器;operand2:第2个操作数;
3.3、大多数时候可以根据CPSR的条件标志位觉得是否该执行指令。当条件满足时才执行,否则不执行。
3.4、arm指令的16个条件码,如下:
3.5、示例代码说明使用条件码以实现高效的逻辑操作:
-
C代码:
-
if(a> b)
-
a++;
-
else
-
b++;
-
对应的汇编代码:
-
CMP R0,R1 ;R0(a)与R1(b)比较
-
ADDHI R0,R0,#1 ;若R0>R1,则R0=R0+1
-
ADDLS R1,R1,#1 ;若R0≤1,则R1=R1+1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
arm指令寻址方式
1、寻址方式是根据指令中给出的地址码字段来实现寻找真实操作数地址的方式。
2、数据处理指令的操作数寻址方式归纳如下:
指令格式:
2.1、立即数方式,必须遵循规则:每一个立即数由一个8位的常数循环右移偶数位得到。公式表达为:立即数 =8位常数循环右移2*4位二进制数 即immediate=const_8 ROR 2*bin_4。
比如,0x104为合法的立即数,而0x101 不是合法的立即数。是不允许在指令中使用的。
2.2、寄存器方式,操作数即为寄存器里的数值
2.3、寄存器移位方式,操作数是寄存器里的数值移位而得到,有如下移位操作:ASR,LSR,LSL,ROR,RRX等。
3、字及无符号字节的load/store指令寻址方式
3.1、load指令从内存读取数据放入寄存器,store指令用于将寄存器中的数据保存到内存。
3.2、以LDR指令为例说明:
LDR指令的编码格式如下:
LDR指令的语法格式如下:
注释:cond是指令执行的条件码,Rd是目的寄存器的编码,Rn和Address_mode一起构成了第二个操作数的内存地址。
3.3、寻址方式由基址寄存器Rn和地址偏移量address_mode两部分组成,其中地址偏移量有三种格式:立即数,寄存器,寄存器及一个移位常数。
3.4、寻址方式的地址计算方法有三种:偏移量方法,事先更新方法(即在指令的内存访问完成后进行基址寄存器内容更新的方式),事后更新方法(在指令的内存访问完成计算新地址的方式)。
3.5、根据寻址方式的地址计算方法和地址偏移量可知第二个操作数的内存地址共有如下9种格式:
以第一种格式为例说明第二个操作数的内存地址的计算方法:
[, #+/- ]表示基址寄存器Rn值加或减偏移量,它的指令编码为:
使用偏移量方法计算内存地址,它的伪代码表示为:
-
if U == 1 then
-
address = Rn + offset_12
-
else /*U = 0*/
-
address = Rn - offset_12
- 1
- 2
- 3
- 4
4、杂类Load/Store指令的寻址方式
4.1、指令的语法格式如下:
4.2、指令中内存单元的寻址方式有以下6种:
4.2、以第三种寻址方式说明内存地址的计算方法
使用该寻址方式[, #+/-]! 的指令编码格式如下:
使用事先更新方法计算内存地址,它的伪代码如下:
-
offset_8 = (immedH << 4) OR immedL
-
if U == 1 then
-
address = Rn + offset_8
-
else /*U = 0*/
-
address = Rn - offset_8
-
if ConditionPassed(cond) then
-
Rn = address
- 1
- 2
- 3
- 4
- 5
- 6
- 7
5、批量Load/Store指令的寻址方式
5.1、指令功能是实现在一组寄存器和一块连续的内存单元之间传输数据
5.2、它的语法格式和指令编码格式如下:
P位表示基址寄存器Rn所指的内存单元是否包含在指令使用的内存块中。
U位表示地址变化的方向
W位表示指令执行后,基址寄存器Rn的值是否更新
L位表示操作的类型
5.3、address_mode表示地址变化方式,有四种,如下所示:
以(DA)事后递减(U=0)方式 为例说明内存地址的计算方法
DA指令编码格式如下:
内存地址的算法,伪代码表示如下:
-
start_address = Rn-(Number_Of_Set_Bits_In(register_list)*4)+4
-
end_address =Rn
-
if ConditionPassed(cond) and W == 1 then
-
Rn = Rn - (Number_Of_Set_Bits_In(register_list) * 4)
- 1
- 2
- 3
- 4
6、协处理器Load/Store指令的寻址方式
6.1、指令的功能是在arm处理器和协处理器之间传输批量数据
6.2、指令的语法格式和编码格式如下:
对各个标志位含义的解释:
U位表示基址寄存器Rn的更新方式
N位一般表示传输数据的字节大小
W位表示指令执行后,基址寄存器Rn的值是否更新
L位表示操作的类型
文章原地址:http://blog.csdn.net/starshinning975/article/details/48580925
参考文章二:
指令基本格式:
<opcode>{<cond>}{S} <Rd>,<Rn>{,<operand2>}
1、<>内的项是必须的,{}内的项是可选的,cond若不附指令后使用默认条件AL(无条件执行)。
2、opcode:指令助记符,如LDR,STR等;
3、cond:执行条件,如EQ,NE等;
4、S:是否影响CPSR寄存器的值;
5、Rd:目标寄存器;
6、Rn:第一个操作数的寄存器;
7、operand2:第二个操作数;ARM指令中,灵活使用第二个操作数可提高代码效率,第二个操作数的形式有:
√#immed_8r ——常数表达式;
√Rm ——寄存器方式;
√Rm,shift ——寄存器移位方式;
其指令编码格式如下:
31-28 | 27-25 | 24-21 | 20 | 19-16 | 15-12 | 11-0(12位) |
cond | 001 | opcode | S | Rn | Rd | shifter_operand |
#immed_8r:
该常数必须对应8位位图(即首尾两个"1"bit间的间距为6bits且该常数通过循环左移偶数位所有bit=1的位必集中在低8bits)。如 0x1FE、511、0xFFFF、0x1010、0xF0000010为非法常量,0x3FC、0、0xF0000000、200、 0xF0000001为合法常量。
利用这种转换巧妙的实现了:在32bits的ARM指令代码中集成32bits的立即数(常数)。如立即寻址的 数据处理指令的指令代码为:xxxx001a aaaSnnnn ddddrrrr bbbbbbbb,则其第二个操作数op2=#b,ROR #2r,由op2到指令码的转换经编译器完成。
对其中的operand2的常数表达式有这样的规定:“该常数必须对应8位位图,即常熟是由一个8位的常熟循环右移偶数位得到的。”这句话的意思是说,当用12位第二操作数来表示一个32位立即数时,采用的是将8位数通过移位的方式来实现的,其中12位第二操作数的低八位存放被移位的“基本”数(取值范围为0到255),而高四位存放的是循环右移的位数,因为位四位二进制数,所以取值范围位为0到15,而对应的移位位数则为0到30位,也就是说若“移位”数为0,则表示“基本”数不变,若“移位”数位1,则表示将“基本”数在32位数字空间中循环右移2位,若“移位”数位5,则表示将“基本”数在32位数字空间中循环右移10位,若“移位”数位10,则表示将“基本”数在32位数字空间中循环右移20位,依次类推。举例表示:
AND R1,R2,#0xff
当处理器处理这条指令的第二操作数0xff时,因为0xff为8位二进制数,所以处理器就将其直接放进8位“基本”数中,而4位“移位”数则为0.
AND R1,R2,#0x104
当处理器处理这条指令的第二操作数0x104时,因为此时0x104已经超过了8位二进制数,所以处理器就要将其“改造”一下,我们先把0x104转换成二进制0000 0000 0000 0000 0000 0001 0000 0100,我们可以看到,这个数是0000 0000 0000 0000 0000 0000 0100 0001通过循环右移30位得到的,因此改造后的结果是8位“基本”数中存放0100 0001,而“移位”数为15。
AND R1,R2,#0xff000000
当处理器处理这条指令的第二操作数0xff000000时,处理器同样要对其“改造”,我们先把0xff000000转换成二进制1111 1111 0000 0000 0000 0000 0000 0000,我们可以看到,这个数是0000 0000 0000 0000 0000 0000 1111 1111通过循环右移8位得到的,因此改造后的结果是8位“基本”数中存放1111 1111,而“移位”数为4。
我想,通过以上的三个例子,就应该明白了8位位图的原理了。但是,有些数并不符合8位位图的原理,这样的数在进行程序编译时,系统将会提示出错,下面再举几个违反8位位图的例子:比如0x101,转换成二进制后位0000 0000 0000 0000 0000 0001 0000 0001,像这个数,无论向右循环几位,都无法将两个1同时放到低8位中,因此不符合8位位图;再比如0x102,转换成二进制后位0000 0000 0000 0000 0000 0001 0000 0010,如果将两个1同时放到低8位中,即转换成二进制后为0000 0000 0000 0000 0000 0000 1000 0001,需要将此二进制数向右移31位,这也不符合循环右移偶数位的条件,因此0x012也不符合8位位图;再举一个0xff1,转换成二进制后将会有9个1,不可能将其同时放入8位中,因此当然也不符合啦。
通过正反例的比较,可以总结如下:第一,判断一个数是否符合8位位图的原则,首先看这个数转换成二进制后1的个数是否不超过8个,如果不超过8个,再看这n个1(n<=8)是否能同时放到8个二进制位中,如果可以放进去,再看这八个二进制位是否可以循环右移偶数位得到起初被判断的那个数值,如果可以,则此数值即为符合8位位图原理,否则,不符合。第二,用12位的编码来表示一个任意的32位数是不可能的,只能通过循环右移八位二进制数偶数位来得到一部分32位数,其余的无法表示的32位数,只有通过其它途径获得了,比如0xffffff00,可以通过0x000000ff按位取反得到,因此在以后的编程中,一定要注意用到的第二操作数是否符合8位位图。
Rm:
在寄存器方式下,第二个操作数即寄存器的数值;
Rm,shift:
在寄存器移位操作方式下,将寄存器的移位结果作为操作数,但Rm的值保持不变,移位方法有下:
其中n取值一般在1--31之间。
8、The ARM instruction set:
9、指令条件码: