ARM 指令集摘要
简介: ARM指令系统一般有Thumb指令集和ARM指令集。
Thumb: 指令集具有灵活、小巧的特点,是16位的
ARM:指令集支持ARM核所有的特性,具有高效、快速的特点,是32位的
一 寻址方式
a) 寄存器寻址(操作数的值在寄存器中)
mov r1, r2 // r1 = r2
b) 立即寻址(操作数在指令中)
mov r1, #0xff00 //r1 = 0xff00
c) 寄存器移位寻址(第2个操作数是寄存器移位方式)
mov r1, r2, lsl #3 //r1 = r2 << 3
d) 寄存器简介寻址(第2个寄存器中给出的是操作数的地址)
ldr r0, [r2] //r0 = [r2]
e) 基址寻址(将基址寄存器的值和指令中的偏移相加得到操作数的地址)
ldr r0, [r1, #0x0c] //r0 = [r1 + 0x0c]
f) 多寄存器寻址(一次可以最多传送16个寄存器的值)
ldmia r1!, {r2-r4, r6} // r2 = [r1], r1 = r1 + 4, r3 = [r1], ……
g) 堆栈寻址(先进后出)
满递增:堆栈向上增长,堆栈指针指向内含有效数据项的最高地址。指令如LDMFA、STMFA等;
空递增:堆栈向上增长,堆栈指针指向堆栈上的第一个空位置。指令如LDMEA、STMEA等
满递减:堆栈向下增长,堆栈指针指向内含有效数据项的最低地址。指令如LDMFD、STMFD等
空递减:堆栈向下增长,堆栈指针向堆栈下的第一个空位置。指令如LDMED、STMED等
h) 块拷贝寻址
STMIA R0!,{R1-R7} ;将R1~R7的数据保存到存储器中。
;存储指针在保存第一个值之后增加,;增长方向为向上增长
STMIB R0!,{R1-R7} ;将R1~R7的数据保存到存储器中。
;存储指针在保存第一个值之前增加,;增长方向为向上增长。
i) 相对寻址: 相对寻址是基址寻址的一种变通。由程序计数器PC提供基准地址,指令中的地址码字段作为偏移量,两者相加后得到的地址即为操作数的有效地址。
bl / beq
二 CPSR(程序状态寄存器)格式
31 30 29 28 27 …… 8 7 6 5 4 3 2 1 0
+--+--+--+--+----------------- +--+--+--+----+-----+----+-----+-----+-
| N | Z | C | V| - | - | ……. -| - | I | F | T | M4| M3 | M2 | M1 | M0 |
+--+--+--+--+-----------------+--+--+--+----+-----+----+-----+-----+-
N: 当用两个补码表示的带符号数进行运算时N=1表示运算结果为负数; N=0表示结果为正或0
Z: Z = 1 表示运算结果为0, Z = 0 表示运算结果为非0
C: 有4中方法设置C, 1) 加法运算: 当结果产生进位时C=1,否则C=0; 2) 减法运算: 当运算产生借位时C=0,否则C=1; 3)对于移位操作, C为移出值的最后一位; 4) 对于其他指令, C的值通常不变.
V: 对于加减运算, 当操作数和结果为2进制补码表示的带符号数时,V=1表示符号为溢出.
I: I=1 禁止IRQ中断
F: F=1 禁止FIQ中断
T T=1 运行于Thumb状态, 否则运行于ARM状态
M[4:0]: 1) 0b10000 用户模式 PC, CPSR, R0-R14 2)
2) 0b10001 FIQ模式 PC, CPSR, SPSR_fiq, R0- R7, R8_fiq – R14_fiq
3) 0b10010 IRQ模式 PC, CPSR, SPSR_irq, R0- R12, R13_irq – R14_irq
4) 0b10011 管理模式 PC, CPSR, SPSR_svc R0- R12, R13_svc – R14_svc
5) 0b10111 终止模式 PC, CPSR, SPSR_abt, R0- R12, R13_abt – R14_abt
6) 0b11011 未定义模式 PC, CPSR, SPSR_und, R0- R12, R13_und – R14_und
7) 0b11111 系统模式 PC, CPSR, R0- R14
三 指令集
1 格式: <opcode>{<cond>}{s} <rd>, <rn>{<operand2>}
opcode:指令助记符; cond:执行条件; S:是否影响CPSR寄存器的值;
Rd:目标寄存器; Rn:第1个操作数的寄存器; operand2:第2个操作数;
灵活的使用第2个操作数“operand2”能够提高代码效率。它有如下的形式:
§ #immed_8r——常数表达式;
§ Rm——寄存器方式;
§ Rm,shift——寄存器移位方式;
常数格式必须为8位常数循环右移偶数位的值.
移位方法有:
操作码 | 说明 | 操作码 | 说明 | |
ASR #n | 算术右移n位 | ROR #n | 循环右移n位 | |
LSL #n | 逻辑左移n位 | RRX | 带扩展的循环右移1位 | |
LSR #n | 逻辑右移n位 | Type Rs | Type为移位的一种类型,Rs为偏移量寄存器,低8位有效。 | |
所有的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 | 正数或零 |
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 | 任何 | 从不执行(不要使用) |
2 指令集:
a)存储器访问指令
1 单寄存器存取
LDR/STR指令用于对内存变量的访问、内存缓冲区数据的访问、查表、外围部件的控制操作等。若使用LDR指令加载数据到PC寄存器,则实现程序跳转功能,这样也就实现了程序散转。
助记符 | 说明 | 操作 | 条件码位置 |
LDR Rd ,addressing | 加载字数据 | Rd←[addressing],addressing索引 | LDR{cond} |
LDRB Rd ,addressing | 加载无符号字节数据 | Rd←[addressing],addressing索引 | LDR{cond}B |
LDRT Rd ,addressing | 以用户模式加载字数据 | Rd←[addressing],addressing索引 | LDR{cond}T |
LDRBT Rd , addressing | 以用户模式加载无符号字节数据 | Rd←[addressing],addressing索引 | LDR{cond}BT |
LDRH Rd , addressing | 加载无符号半字数据 | Rd←[addressing],addressing索引 | LDR{cond}H |
LDRSB Rd , addressing | 加载有符号字节数据 | Rd←[addressing],addressing索引 | LDR{cond}SB |
LDRSH Rd , addressing | 加载有符号半字数据 | Rd←[addressing],addressing索引 | LDR{cond}SH |
助记符 | 说明 | 操作 | 条件码位置 |
STR Rd , addressing | 存储字数据 | [addressing]←Rd, addressing索引 | STR{cond} |
STRB Rd ,addressing | 存储字节数据 | [addressing]←Rd, addressing索引 | STR{cond}B |
STRT Rd ,addressing | 以用户模式存储字数据 | [addressing]←Rd, addressing索引 | STR{cond}T |
STRBT Rd ,addressing | 以用户模式存储字节数据 | [addressing]←Rd, addressing索引 | STR{cond}BT |
STRH Rd ,addressing | 存储半字数据 | [addressing] ←Rd, addressing索引 | STR{cond}H |
LDR R2,[R5] ;将R5指向地址的字数据存入R2
ldr rd, [rd1], #0x04 // rd = [rd1], rd1 = rd1 + 0x04
STR R1,[R0,#0x04] ;将R1的数据存储到R0+0x04地址
str rd, [rd1], #4 // [rd1] = rd, rd1 = rd1 + 4
LDRB R3,[R2],#1 ;将R2指向地址的字节数据存入R3,R2=R2+1
STRB R6,[R7] ;将R7指向地址的字节数据存入R6
LDRSB R1,[R0,R3] ;将R0+R3地址上的字节数据存入R1,高24位用符号扩展
LDRH R6,[R2],#2 ; ;将R2指向地址的半字数据存入R6,高16位用0扩展读出后,R2=R2+2
STRH R1,[R0,#2]! ;将R1的半字数据保存到R0+2地址,只修改低2字节数据,R0=R0+2
str r1, [r0, #2]! ;( [r0 + 2] = r1, r0 = r0 + 2)
2. 多寄存器操作
多寄存器加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM为加载多个寄存器;STM为存储多个寄存器。允许一条指令传送16个寄存器的任何子集或所有寄存器。它们主要用于现场保护、数据复制、常数传递等
LDM{cond}<mode> Rn{!}, reglist{^} //多寄存器加载 reglist ß [Rn…],
STM{cond}<mode> Rn{!}, reglist{^} //多寄存器存储 [Rn…] ß reglist
cond为条件码, mode为控制地址的增长方式, !表示在操作结束后,将结果写回Rn, ^为当进行数据传送且寄存器列表不含pc时,加载/存储的寄存器是用户模式下的, 若在LDM下使用PC,则除正常的寄存器操作外,还将SPSR拷贝到CPSR中(它不能用在用户和系统模式下), reglist :表示寄存器列表,可以包含多个寄存器,它们使用“,”隔开,如{R1,R2,R6-R9},寄存器由小到大排列;
mode:
模式 | 说明 | 模式 | 说明 |
IA | 每次传送后地址加4 | FD | 满递减堆栈 |
IB | 每次传送前地址加4 | ED | 空递减堆栈 |
DA | 每次传送后地址减4 | FA | 满递增堆栈 |
DB | 每次传送前地址减4 | EA | 空递增堆栈 |
数据块传送操作 | 堆栈操作 |
进行数据复制时,先设置好源数据指针和目标指针,然后使用块拷贝寻址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB进行读取和存储 。
进行堆栈操作操作时,要先设置堆栈指针(SP),然后使用堆栈寻址指令STMFD/LDMFD 、STMED/LDMED、STMFA/LDMFA和STMEA/LDMEA实现堆栈操作。
STMDA r0!, {r5-r6} … LDMIB r0!, {r5-r6}
STMED r0!, {r5, r6} …. LDMED r0!, {r5-r6}
b) 寄存器和存储器交换指令
SWP{cond}{B} Rd, Rm, [Rn] Rd ß[Rn] , [Rn] ß Rm
swp r1, r1, [r0] 将R1的内容与R0指向的存储单元的内容进行交换
swpb r1, r2, [r0] 将R0指向的存储单元的内容读取一个字节存入R1,并将R2的内容写入该内存单元
c) 数据处理指令
1 数据传送
MOV{cond}{S} Rd, operand2 Rd ß operand2 如 mov r1, #0x10 / movs r3, r1, lsl, #2
MVN{cond}{s} Rd, operand2 Rd ß (~operand2) 如 mvn r1, #0xff ; r1=0xffffff00
2 算术指令
ADD{cond}{S} Rd, Rn, operand2 ;Rd ßRn+operand2 如 add r1, r1, r2 ; r1 = r1 + r2
SUB{cond}{S} Rd, Rn, operand2 ;Rd ß Rn – operand2 如 subs r0, r0, #1 ; r0 = r0 – 1
RSB{cond}{S} Rd, Rn, operand2 ;Rd ßoperand2 –Rn 如 rsb r3, r1, #0xff00 ; r3 = 0xff00 – r1
ADC{cond}{S} Rd, Rn, operand2 ;Rd ß Rn + operand2 + Carry 如 adc r1, r1, r3 ; r1 = r1 + r3 +进位标志
SBC{cond}{S} Rd, Rn, operand2 ;Rd ßRn – operand2 – (Not)Carry 如 sbc r1, r1, r3; r1=r1–r3–借位标志
RSC{cond}{S} Rd, Rn, operand2 ;Rd ßoperand2 – Rn – (Not)Carry 如 rsc r3, r1, #0
3 逻辑运算指令
AND{cond}{s} Rd, Rn, operand2 Rd ßRn & operand2 如 and r2, r1, r3 ; r2 = r1 & r3
ORR{cond}{s} Rd, Rn, operand2 Rd ß Rn |operand2 如 orr r0, r0, #0x0f ; r0 = r0 | 0x0f
EOR{cond}{s} Rd, Rn, operand2 Rd ß Rn ^ operand2 如 eor r1, r1, #0x0f ; r1 = r1 ^ 0x0f
BIC{cond}{s} Rd, Rn, operand2 Rd ß Rn &( ~operand2) 如 bic r1, r1, #0x0f ;将R1的低4位清0
4 比较指令
CMP{cond} Rn, operand2 标志N,Z,C,V ß Rn – operand2 如 cmp r1, #10 ;R1与10比较,设置相关标志位
CMN{cond} Rn, operand2 标志N,Z,C,V ß Rn + operand2 如 cmn r1, #1 ;R0+1,判断R0是否为1的补码
如果是,则设置Z标志位
TST{cond} Rn, operand2 标志N,Z,C,V ß Rn & operand2 如 tst r1, #0x01 ;判断R0的最低位是否为0
TEQ{cond} Rn, operand2 标志N,Z,C,V ß Rn ^ operand2 如 teq r0, r1 ;比较R0与R1是否相等 (不影响V位和C位)
5 乘法指令
1 32位乘法
MUL{cond}{s} Rd, Rm, Rs Rd ßRm * Rs (Rd != Rm) Mul r1, r2, r3 ; r1 = r2 * r3
MLA{cond}{s} Rd, Rm, Rs,Rn Rd ßRm * Rs + Rn (Rd != Rm) Mla r1, r2, r3, r0 ; r1 = r2 * r3 + r0
2 64位
UMULL{cond}{s} RdLo, RdHi, Rm,Rs (RdLo.RdHi) ß Rm * Rs Umull r0, r1, r5, r8 ;(r1,r0) = r5 * r8
UMLAL{cond}{s} RdLo, RdHi, Rm,Rs (RdLo.RdHi) ß Rm * Rs +(RdLo.RdHi)
umlal r0, r1, r5, r8 ;(r1,r0) = r5 * r8 + (r1, r0)
SMULL{cond}{s} RdLo, RdHi, Rm,Rs (RdLo.RdHi) ß Rm * Rs Smull r2,r3, r7, r6 ;(r3,r2) = r7 * r6
SMLAL{cond}{s} RdLo, RdHi, Rm,Rs (RdLo.RdHi) ß Rm * Rs +(RdLo.RdHi)
smlal r2, r3, r7, r6 ;(r3,r2) = r7 * r6 + (r3, r2)
d) 分支指令
B{cond} Label PCß label B WAITA ;跳转到WAITA标号处
BL{cond} Label LRßPC – 4, PC ß label ;BL delay ;调用子程序delay,delay结束会后将lr存入PC,即返回
BX{cond} Rm PCßRm, 切换处理器状态(通过Rm[0]指示) BX R0;跳转到R0,并根据R0的最低位来切换处理器状态
e) 协处理器指令
CDP{cond} coproc, opcode1, CRd, CRn, CRm{, opcode2} //通知协处理器执行特定的操作
CDP p7,0,c0,c2,c3,0 ;对协处理器7操作,操作码为0,可选操作码为0
LDC{cond}{L} coproc, CRd, <地址> 数据读取指令
LDC p5,c2,[R2,#4] ;读取R2+4指向的内存单元的数据,传送到协处理器p5的c2寄存器中
STC{cond}{L} coproc, CRd, <地址> 数据存储指令
STC p5,c1,[R0] ;将协处理器p5的C1寄存器内数据传送到R0指向的内存单元
MCR{cond} coproc,opcode1, Rd, CRn, CRm{,opcode2} //寄存器间数据交换(ARM à 协处理器)
MCR p6,2,R7,c1,c2 ;将ARM中的R7寄存器内容传递到协处理器6的C1和C2寄存器
MRC{cond} coproc,opcode1, Rd, CRn, CRm{,opcode2} //寄存器间数据交换(协处理器à ARM)
MRC p5,2,R2,c3,c2 ;将协处理器5的C3和C2寄存器内容传递到ARM中的R2寄存器
f) 杂项指令
SWI{cond} immed_24 产生软中断,处理器进入管理模式,并且将CPSR保存到管理模式的SPSR中
SWI 12 ;调用12号软中断
MRS{cond} Rd, psr Rd ß psr psr为CPSR,SPSR
MRS R1,CPSR ; 将CPSR状态寄存器读取,保存到R1中
MSR{cond} psr_fields, Rd / immed_8r psr_fields ßRd / immed_8r,
fields:c(psr[7..0]), x(psr[15..8]), s(psr[23…16]), f(psr[31…24])的一个组合
g) 伪指令
ADR{cond} register, expr //将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中
ADR R0, delay ; 将标号delay的地址存入R0
……
Delay
Mov r0, r14
ADRL{cond} register, expr //将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR可以读取更大范围的地址, 用法同ADR
LDR{cond} register, =expr //用于加载32位的立即数或一个地址值到指定寄存器
LDR R0, =delay ; 将标号delay的地址存入R0
……
Delay:
Mov r0, r14
与LDR指令相比, 此伪指令的操作数有 “ = ”
NOP 空操作