共有7种运行模式:
1 用户模式 user,用户程序执行的模式
2 快速中断模式 FIQ,用于高速数据传输和通道处理
3 外部中断模式 IRQ,用于通常的中断处理
4 特权模式 Supervisor svc,供操作系统使用的一种保护模式
5 数据访问中止模式 Abort abt,用于虚拟存储和存储保护
6 未定义指令中止模式 Undefined und,支持通过软件方针硬件的协处理
7 系统模式 System sys,用于运行特权级的操作系统任务
除了用户模式,其他6种模式称为特权模式(Privileged Modes)可以访问所有的系统资源。
ARM共有37个寄存器。31个通用寄存器,包括PC寄存器。6个状态寄存器。这些寄存器都是32位的,但是6个状态寄存器只使用了其中12位。上述这些寄存器,在不同的模式下,可能共用,或者特定模式下有它自己独有的寄存器,如表1所示。
表1 各种处理器模式下的寄存器。
用户模式 | 系统模式 | 特权模式 | 中止模式 | 未定义指令模式 | 外部中断模式 | 快速中断模式 |
R0 | R0 | R0 | R0 | R0 | R0 | R0 |
R1 | R1 | R1 | R1 | R1 | R1 | R1 |
R1 | R1 | R1 | R1 | R1 | R1 | R1 |
R3 | R3 | R3 | R3 | R3 | R3 | R3 |
R4 | R4 | R4 | R4 | R4 | R4 | R4 |
R5 | R5 | R5 | R5 | R5 | R5 | R5 |
R6 | R6 | R6 | R6 | R6 | R6 | R6 |
R7 | R7 | R7 | R7 | R7 | R7 | R7 |
R8 | R8 | R8 | R8 | R8 | R8 | |
R9 | R9 | R9 | R9 | R9 | R9 | R9_fiq |
R10 | R10 | R10 | R10 | R10 | R10 | R10_fiq |
R11 | R11 | R11 | R11 | R11 | R11 | R11_fiq |
R12 | R12 | R12 | R12 | R12 | R12 | R12_fiq |
R13 | R13 | R13_svc | R13_abt | R13_und | R13_irq | R13_fiq |
R14 | R14 | R14_svc | R14_abt | R14_und | R14_irq | R14_fiq |
PC | PC | PC | PC | PC | PC | PC |
CPSR | CPSR | CPSR | CPSR | CPSR | CPSR | CPSR |
SPSR_svc | SPSR_abt | SPSR_und | SPSR_irq | SPSR_fiq |
包括
R0-R7,未备份寄存器 the unbanked registers,所有模式都共用。
R8-R14,备份寄存器 the banked registers。有些模式有它自己的备份寄存器。
PC,程序计数器,即R15。
R13通常用于栈指针。ARM指令集也可以用其它寄存器做栈指针,但是Thumb指令集中,某些指令强制使用R13作为栈指针。
R14又被称为连接寄存器 Link Register LR。其有两种特殊用途:
1 存放当前子程序的返回地址。
2 异常中断发生时,存放异常模式将要返回的地址。
R15 程序计数器
又被记作PC。PC的值为当前指令地址值加8个字节。也就是说,PC指向当前指令的下两条指令的地址。
CPSR当前程序状态寄存器,任何模式都共享这个寄存器。SPSR备份程序状态寄存器,在异常模式下用来备份CPSR,当从异常模式退出时,用SPSR来恢复CPSR。
用户模式和系统模式不是异常中断模式,所以它们没有SPSR。
CPSR的格式如下:
31 | 30 | 29 | 28 | 27 | 26 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
N | Z | C | V | Q | DNM(RAZ) | I | F | T | M4 | M3 | M2 | M1 | M0 |
条件标志位
N(Negative) Z(Zero) C(Carry) V(oVerflow)
Q标志位
在ARM v5的E系列处理器中,指示增强的DSP指令是否发生溢出。
控制位
低8位,I F T及M[4:0]
当异常中断发生时,这些位发生变化。在6种特权级的处理器模式下,软件可以修改这些控制位。
I 中断禁止位,设置为1,将禁止IRQ中断。
T控制位,指示是ARM指令还是Thumb指令。不同的ARM处理器,T的含义可能不同。
M控制位,控制处理器模式。
10000 |
user |
10001 |
FIQ |
10010 |
IRQ |
10011 |
Supervisor |
10111 |
Abort |
11011 |
Undefined |
11111 |
System |
ARM指令执行流程有3种:
1 正常执行过程,根据PC,一条条执行。
2 跳转执行。
3 异常中断执行。
ARM异常中断类型
复位 Reset,上电/硬件复位/软件复位时。
未定义指令 undefined instruction
软中断 software interrupt SWI
指令预取中止 Prefech abort
数据访问中止 Data Abort
外部中断请求 IRQ
外部快速中断请求 FIQ
进入中断要做的事情
将CPSR备份到SPSR,设置当前CPSR的相应位,如关闭中断,将返回地址存储到R14,设置PC,跳到中断处理程序处执行。
从中断返回要做的事情
恢复CPSR。返回到R14指向的地址继续执行。
ARM通常以4字节对齐,如果访问未对其的数据地址或指令地址,将导致未知的结果。
指令预取
一次取出多条指令
自修改代码
在代码的执行过程种,可能修改代码。
ARM指令集可以分为6类:
跳转指令
数据处理指令
程序状态寄存器(PSR)传输指令
Load/Store指令
协处理器指令
异常中断产生指令
一条典型的指令
31 |
27 |
24 |
20 |
19 |
15 |
11 |
cond |
001 |
opcode |
S |
Rn |
Rd |
shifter operand |
cond 指令执行的条件编码
opcode 指令操作符编码
S 指令的操作是否影响CPSR的值
Rd 目标寄存器编码
Rn 包含第一个操作数的寄存器编码
shifter_operand 表示第二个操作数
典型的ARM指令语法格式
<opcode> {<cond>} {S} <Rd>, <Rn>, <shifter operand>
ARM指令的31-28,共4位为条件码,根据CPSR中的条件标志位决定是否执行该指令。条件满足时执行,不满足时当作一条NOP指令。
表2 指令的条件码
条件码 <cond> | 条件码 助记符 | 含义 | CPSR种条件标志位值 |
0000 | EQ | 相等 | Z=1 |
0001 | NE | 不相等 | Z=0 |
0010 | CS/HS | 无符号数大于或等于 | C=1 |
0011 | CC/LO | 无符号数小于 | C=0 |
0100 | ML | 负数 | 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=1且V=1 或 N=0且V=0 |
1011 | LT | 带符号数小于 | N=1且V=0 或N=0且V=1 |
1100 | GT | 带符号数大于 | Z=0且N=V |
1101 | LE | 带符号数小于或等于 | Z=1且N!=V |
1110 | AL | 无条件执行 | |
1111 | NV 未定义 AL | 从不执行 结果不可预知 无条件执行 | ARM v3之前 ARM v3及v4 ARM v5及以上版本 |
不同的指令类型,其操作数有不同的寻址方式。
数据处理指令的格式如下:
<opcode> {<cond>} {S} <Rd>,<Rn>,<shifter_operand>
shift operand有3种寻址方式:立即数/寄存器/寄存器移位
1 立即数
由于shift operand只有12位,它包含两个部分immed_8和immed_4。立即数的值为:
immediate = immed_8 << ( 2 * immed_4)
一个立即数可能有多种immed_8和immed_4的组合,ARM汇编器选择最小的immed_4的那种组合。
2 寄存器方式
在某些指令中,shift operand表示某个寄存器。如
ADD R0, R1, R2
3 寄存器移位方式
包含寄存器及其移位的位数,同时位数可以用立即数或者寄存器表示。移位的方式有:
ASR 算数右移
LSL 逻辑左移
LSR 逻辑右移
ROR 循环右移
RRX 扩展的循环右移
如:
MOV RO,R1,LSL #3
MOV R0,R1,ROR R2
具体的寻址方式有下面11种
#<immediate>
<Rm>
<Rm>, LSL #<shift_imm>
<Rm>, LSL <Rs>
<Rm>, LSR #<shift_imm>
<Rm>, LSR <Rs>
<Rm>, ASR #<shift_imm>
<Rm>, ASR <Rs>
<Rm>, ROR #<shift_imm>
<Rm>, ROR <Rs>
<Rm>, RRX
Load指令用于从内存中读取数据放入寄存器。Store指令用于将寄存器中的数据保存到内存中。
寻址方式分为两部分:基址寄存器,地址偏移量。
基址寄存器可以为任一个通用寄存器。
偏移量有3种格式:
立即数
寄存器
寄存器及一个移位常数
地址计算方法有3种:
偏移量方法
事先更新方法
事后更新方法
LDR指令格式:
31 |
27 |
25 |
24 |
23 |
22 |
21 |
20 |
19 |
15 |
11 |
cond |
01 |
I |
P |
U |
0 |
W |
1 |
Rn |
Rd |
Address_mode |
Rd目标期存器
Rn基址寄存器
Address_mode 偏移量
语法格式
LDR {<cond>} {B} {T} <Rd>,<address_mode>
address mode共有9种模式
1 [<Rn>, #+/-<offset_12>]
立即数做偏移量。
U:1加偏移量,0减偏移量。
B:1无符号,0有符号。
L:1执行Load,0执行Store。
示例:
LDR R0,[R1,#4]
LDR R0,[R1,#-4]
2 [<Rn>, +/-<Rm>]
寄存器做偏移量
示例
LDR R0,[R1,R2]
LDR R0,[R1,-R2]
3 [<Rn>,+/-<Rm>,<shift_typet>#<shift_imm>]
寄存器移位做偏移量,共有5种
[<Rn>,+/-<Rm>,LSL#<shift_imm>]
[<Rn>,+/-<Rm>,LSR#<shift_imm>]
[<Rn>,+/-<Rm>,ASR#<shift_imm>]
[<Rn>,+/-<Rm>,ROR#<shift_imm>]
[<Rn>,+/-<Rm>,RRX]
4 立即数方式的事先访问方式 pre-indexed
[<Rn>,#+/-<offset_12]!
指令执行完后,地址写入Rn。
LDR R0,[R1,#4]!
5 寄存器方式的事先访问方式
[<Rn>,+/-<Rm>]!
6 寄存器移位方式的事先访问方式
[<Rn>,+/-<Rm>,<shift_typet>#<shift_imm>]!
7 事后访问方式
[<Rn>],#+/-<offset_12>
如:LDR R0,[R1],#4 将地址R1的内存单元数据读取到R0中,然后R1+=4。
8 [<Rn>],+/-<Rm>
9 [<Rn>],+/-<Rm>,<shift_type>#<shift_imm>
B跳转指令
BL 带返回的跳转指令,将PC寄存器的值保存到LR寄存器中。
B{L} {<cond>} <target_address>
将24位带符号的补码立即数扩展为32位,然后左移2位,加上PC值,得到跳转后的地址。
跳转范围:PC +/- 32MB
格式
31 |
27 |
24 |
23 |
cond |
101 |
L |
signed immed 24 |
L:是否保存PC到LR寄存器。
BLX跳转指令
BLX <target_address>
BLX {<cond>} <Rm>
BX指令
BX {<cond>} <Rm>
分为3类:
数据传送指令,向寄存器传入一个常数。
算数逻辑运算指令
比较指令,不保存运算结果,只更新CPSR中相应的条件标志位。
1 MOV传送指令
将<shifter_operand>表示的数据传送到目标寄存器<Rd>中,并根据操作的结果更新CPSR中相应的标志位。
MOV {<cond>} {S} <Rd>,<shifter_operand>
2 MVN传送指令
数据的反码送到目标寄存器Rd。
3 ADD加法指令
ADD {<cond>} {S} <Rd>,<Rn>,<shifter_operand>
如:
ADD Rx, Rx, #1
ADD Rd, Rx, Rx, LSL #n
4 ADC带位加法
加上CPSR中的C条件标志位的值。
5 SUB减法指令
SUB {<cond>} {S} <Rd>, <Rn>, <operand>
同ADD。
6 SBC带位减法指令
7 RSB逆向减法指令
RSB {<cond>} {S} <Rd>, <Rn>, <operand>
用操作数减Rn,赋值到Rd。
8 RSC带位逆向减法。
9 AND逻辑与指令
AND {<cond> {S} <Rd>,<Rn>,<shifter_operand>
10 ORR逻辑或指令
ORR {<cond> {S} <Rd>,<Rn>,<shifter_operand>
11 EOR逻辑异或指令
EOR {<cond> {S} <Rd>,<Rn>,<shifter_operand>
12 BIC位清楚指令
BIC {<cond> {S} <Rd>,<Rn>,<shifter_operand>
13 CMP比较指令
CMP {<cond>} <Rn>, <shifter_operand>
14 CMN基于相反数的比较指令
CMN {<cond>} <Rn>, <shifter_operand>
15 TST位测试指令
TST {<cond>} <Rn>, <shifter_operand>
16 TEQ相等测试指令
TEQ {<cond>} <Rn>, <shifter_operand>
有两类乘法指令:32位乘法,结果为32位。另一类是64位乘法指令,结果为64位。
乘法指令的所有操作数都是寄存器。
1 MUL 32位乘法
MUL {<cond>} {S} <Rd>,<Rm>,<Rs>
Rd=Rm*Rs
2 MLA 32位乘加指令
MLA {<cond>} {S} <Rd>,<Rm>,<Rs>,<Rn>
Rd=Rm*Rs + Rn
3 SMULL 64位有符号数乘法指令
SMULL {<cond>} {S} <RdLo>,<RdHi>,<Rm>,<Rs>
实现的是两个32位有符号数的乘积
4 SMLAL 64位有符号乘加
SMLAL {<cond>} {S} <RdLo>,<RdHi>,<Rm>,<Rs>
Rd = Rd+Rm*Rs
5 UMULL 64位无符号乘法
UMULL {<cond>} {S} <RdLo>,<RdHi>,<Rm>,<Rs>
6 UMLAL
UMLAL {<cond>} {S} <RdLo>,<RdHi>,<Rm>,<Rs>
1 CLZ前导0个数计数
CLZ {<cond>} <Rd>,<Rm>
用于在状态寄存器和通用寄存器之间传送数据
1 MRS
将状态寄存器拷贝到通用寄存器
MRS {<cond>} <Rd>, CPSR
MRS {<cond>} <Rd>, SPSR
2 MSR
将通用寄存器或者一个立即数拷贝到状态寄存器
MSR {<cond>} CPSR_<fileds> , #<immediate>
MSR {<cond>} CPSR_<fields>, #<immediate>
MSR {<cond>} CPSR_<fileds>, <Rm>
MSR {<cond>} SPSR_<fields>, #<immediate>
MSR {<cond>} SPSR_<fileds>, <Rm>
fields共4个:
31:24 条件标识域f
23:16 状态位域 s
15:8 扩展位域 x
7:0 控制位域 c
Load从内存中读取数据放入寄存。
Store将寄存器中的内容保存到内存。
1 LDR 字数据读取指令
从内存中读取32位的数据到目标寄存器。
LDR {<cond>} <Rd>, <addressing_mode>
2 LDRB 字节数据读取指令
读取8位数据到寄存器,并将寄存器的高24位清零。
LDR{<cond>}B <Rd>, <addressing_mode>
3 LDRBT 用户模式字节数据读取指令
在其它模式如特权模式下使用用户模式下的内存访问操作。
LDR{<cond>}BT <Rd>, <post_indexed_addressing_mode>
4 LDRH 16位数据存取指令
寄存器的高16位将被清0。
LDR{<cond>}H <Rd>, <addressing_mode>
5 LDRSB 有符号字节读取指令
将8位扩展为寄存器32位有符号数。
LDR{<cond>}SB <Rd>, <addressing_mode>
6 LDRSH 有好符号的半字读取指令
将16位扩展为寄存器32位有符号数。
LDR{<cond>}SH <Rd>, <addressing_mode>
7 LDRT 用户模式的字数据读取指令
LDR{<cond>}T <Rd>, <post_indexed_addressing_mode>
8 STR字数据写入指令
将寄存器的32位写入内存。
STR{<cond>} <Rd>, <addressing_mode>
9 STRB字节写入指令
将寄存器的低8位写入内存。
STR{<cond>}B <Rd>, <addressing_mode>
10 STRH 半字数据写入指令
将寄存器的低16位写入内存。
STR{<cond>}H <Rd>, <addressing_mode>
11 STRT 用户模式的字数据写入指令
STR{<cond>}T <Rd>, <post_indexed_addressing_mode>
12 STRBT用户模式的字节数据写入指令
STR{<cond>}BT <Rd>, <post_indexed_addressing_mode>
语法格式
LDM/STM {<cond>} <addressing_mode> Rn{!}, <registers>{^}
1 LDM(1) 批量内存字数据读取指令
LDM {<cond>} <addressing_mode> Rn{!}, <registers>
2 LDM(2) 用户模式的批量内存字数据读取指令
LDM {<cond>} <addressing_mode> Rn{!}, <registers_without_pc>^
3 LDM(3) 带状态寄存器的批量内存字数据读取指令
该指令会将SPSR寄存器的内容复制到CPSR寄存器中。
LDM {<cond>} <addressing_mode> Rn{!}, <registers_and_pc>^
该指令通常用于从中断中返回
4 STM(1) 批量内存写入指令
STM {<cond>} <addressing_mode> Rn{!}, <registers>
5 STM(2)用户模式的批量内存写入指令
STM {<cond>} <addressing_mode> Rn{!}, <registers>^
1 SWP交换指令
将一个内存单元的内容读取到一个寄存器,将另一个寄存器的内容写入到内存单元。
SWP {<cond>} <Rd>, <Rm>, [<Rn>]
将Rn表示内存的数据读取到Rd,将Rm的数据写入到内存。Rd和Rm可以为同一个寄存器。
2 SWPB 8位字节交换指令
1 SWI软中断指令
SWI{<cond>} <immed_24>
2 BKPT断点中断指令
用于产生软件断点中断,软件调试程序可以使用该中断。
BKPT <immediate>
1 CDP 协处理器数据操作指令
CDP{<cond>} <coproc>, <opcode_1>, <CRd>, <CRm>, <opcode_2>
CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
coproc:协处理器的编码
opcode_1:协处理器的操作码
CRd:作为目标寄存器的协处理器寄存器
CRn:存放第一个操作数的协处理器寄存器。
CRm:存放第二个操作数的协处理器寄存器。
opcode_2:协处理器的操作码
2 LDC 协处理器数据读取指令
从系列连续的内存单元中读取数据到协处理器的寄存器中。
LDC{<cond>} {L} <coproc>, <CRd>, <addressing_mode>
LDC2{L} <coproc>, <CRd>, <addressing_mode>
3 STC协处理器写入指令
将协处理器的寄存器中的数据写入到一系列内存单元中
STC{<cond>} {L} <coproc>, <CRd>, <addressing_mode>
STC2{L} <corpoc>, <CRd>, <addressing_mode>
4 MCR ARM寄存器到协处理器寄存器的数据传送指令
MCR{<cond>} <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>{, <opcode_2>}
MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>{,<opcode_2>}
5 MRC协处理器寄存器到ARM寄存器的数据传送指令
MRC{<cond>} <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>{, <opcode_2>}
MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>{,<opcode_2>}
ARM中断类型
中断名称 | 跳转入口地址 | 含义 |
复位 | 0x0 | 复位引脚有效时,系统产生复位异常中断。 |
未定义指令 | 0x4 | |
软中断 SWI | 0x8 | |
指令预取中止 prefech abort | 0x0c | 预取的指令地址不存在,或不允许访问。 |
数据访问中止 Data abort | 0x10 | |
外部中断请求 | 0x18 | |
快速中断请求 | 0x1c |
共有8种异常中断,异常中断向量表共32个字节,每种4个字节。