ARM指令格式
ARM采用的是32位架构
ARM约定:
- Byte(字节):8 bits
- Halfword(半字):16bits (2 bytes)
- Word(字):32 bits (4 byte)
大部分ARM core提供:
- ARM指令集(32-bits)
- Thumb 指令集(T变种)(16-bit)
ARM指令集是以32位二进制编码的方式给出的,大部分的指令编码中定义了第一操作数、第二操作数、目的操作数、条件标志影响位以及每条指令所对应不同功能实现的二进制位。
- 每条指令的多功能
- ARM指令一个·重要的特点是它所有的指令都带有条件,例如用户可以测试某个寄存器的值,但是,直到下一次使用同一条件进行测试时,才能有条件的执行这些指令。
- ARM指令另一个重要的特点是具有灵活的第二操作数,既可以是立即数,也可以是逻辑运算数,使得ARM指令可以在读取数值的同时进行算术和移位操作。它可以在几种模式下操作,包括通过使用SWI(软件中断)指令从用户模式进入系统模式
ARM指令集——条件码
ARM指令的基本格式如下:
<opcode> {<cond>} {S} <Rd> ,<Rn>{,<operand2>}
使用条件码“cond”可以实现高效的逻辑操作,提高代码效率。
所有的ARM指令都可以条件执行,而Thumb指令只有B(跳转)指令具有条件执行功能,如果指令不标明条件代码,将默认为无条件(AL)执行。
指令条件码表
| 操作码 | 条件助记符 | 标志 | 含义 |
|---|---|---|---|
| 0000 | EQ | Z=1 | 相等 |
| 0001 | NE | Z=0 | 不相等 |
| 0010 | CS/HS | C=1 | 无符号数大于或等于 |
| 0011 | CC/LO | C=0 | 无符号数小于 |
| 0100 | MI | N=1 | 负数 |
| 0101 | PL | N=0 | 正数或0 |
| 0110 | VS | V=1 | 溢出 |
| 0111 | VC | V=0 | 没有溢出 |
| 1000 | HI | C=1,Z=0 | 无符号数大于 |
| 1001 | LS | C=0,Z=1 | 无符号数小于或等于 |
| 1010 | GE | N=V | 有符号数大于或等于 |
| 1011 | LT | N!= V | 有符号数小于或等于 |
| 1100 | GT | Z=0,N=V | 有符号数大于 |
| 1101 | LE | Z=1, N!=V | 有符号数小于或等于 |
| 1110 | AL | 任何 | 无条件执行(指令默认条件) |
| 1111 | NV | 任何 | 从不执行 |
示例1:
C代码: 对应的汇编代码如下,其R0为a,R1为b
if(a > b) CMP R0, R1 ;R0与R1比较
a++; ADDHI R0,R0,#1 ;若R0>R1,则R0 = R0+1
else
b++; ADDLS R1,R1,#1 ;若R0<=R1,则R1 = R1+1
示例2:
C代码:
if((a!=10) && (b!=20))
a=a+b
对应的汇编代码如下,其R0为a,R1为b
CMP R0, #10 ;比较R0是否为10
CMPNE R1,#20 ;若R0不为10,则比较R1是否为20
ADDNE R0,R0,R1 ;若R0不为10且R1不为20,则执行R0=R0+R1
——从这里我们发现条件码需要上一条指令满足条件才执行
ARM基本格式成员说明
ARM指令的基本格式如下:
<opcode> {<cond>} {S} <Rd> ,<Rn>{,<operand2>}
其中<>号内的项是必须的,{}号内的项是可选的。
各项的说明如下:
- opcode:指令助记符
- cond:执行条件
- S:是否影响CPSR寄存器的值
- Rd:目标寄存器
- Rn:第一个操作数的寄存器
- operand2:第2个操作数
ARM指令格式举例
LDR R0, [R1] ;读取R1地址上的存储单元内容,执行条件AL;
BEQ DATAEVEN ;条件执行分支指令,执行条件EQ,即相等则跳转到DATAEVEN;
ADDS R2, R1, #1 ;加法指令,R2<-R1+1,影响CPSR寄存器;
SUBNES R2, R1,#0x20 ;条件执行的减法运算,执行条件NE,R1-0x20->R2,影响CPSR寄存器
ARM指令集——第2个操作数
ARM指令的基本格式如下:
<opcode> {<cond>} {S} <Rd> ,<Rn>{,<operand2>}
灵活的使用第2个操作数"operand2"能够提高代码效率。
它有如下的形式:
- #immed_8r——常数表达式
- Rm————— 寄存器方式(操作数即为寄存器的数值)
- Rm,shift——寄存器位移方式
#immed_8r——常数表达式
该常数必须对应8位位图(pattern),即一个8位的常数通过循环右移偶数位得到,为合法常量。
例如:
MOV R0,#1 ;R0 = 1
AND R1,R2,#0X0F ;R2与0X0F,结果保存在R1中
LDR R0,[R1], #-4;读取R1地址上的存储单元内容,且R1=R1-4
合法常量:
0xFF、0x104、0xFF0、0xFF000、0xFF000000、0xF000000F
0xFF0等于0xFF左移4位,相当于右移28位
非法常量:
0x101、0x102、0xFF1、0xFF04、0xFF003、0xFFFFFFFF
Rm,shift——寄存器移位方式
将寄存器的位移结果作为操作数,但Rm值保持不变,位移方法如下:
| 操作码 | 说明 | 操作码 | 说明 |
|---|---|---|---|
| LSL #n | 逻辑左移n位(1<=n<=31) | ASR #n | 算术右移n位(1<=n<=32) |
| LSR #n | 逻辑右移n位(1<=n<=32) | ROR #n | 循环右移n位(1<=n<=31) |
| ASL #n | 算术左移n位(与LSL同义) | RRX | 带扩展的循环右移1位 |
逻辑左移n位,就等于*2的n次方
例如:
ADD R1,R1,R1,LSL #3 ;R1=R1+R1*8 = 9R1
SUB R11,R12,R3,LSL #32 ; 32超出了LSL范围
MOVS R4,R4,RRX #3 ; RRX不需要指定移位量,RRX总是右移一位
·
ARM指令详解:格式、条件码与操作数
本文介绍了ARM指令格式,包括32位架构的ARM指令集和 Thumb 指令集。详细讲解了ARM指令的条件码、基本格式及成员说明,并通过例子解析了第二操作数的常数表达式和寄存器移位方式,展示了如何实现高效逻辑操作。
1万+

被折叠的 条评论
为什么被折叠?



