ARM指令集
ARM指令的基本格式
ARM指令的基本格式为:
<Opcode> {<Cond>} {S} <Rd>, <Rn> { , <Opcode2> }
其中,<>内的项是必需的,{}内的项是可选的。
1)Opcode项
Opcode是指令助记符,即操作码,说明指令需要执行的操作,在指令中是必需的。
2)Cond项(command)
Cond项表明了指令的执行的条件,每一条ARM指令都可以在规定的条件下执行,每条ARM指令包含4位的条件码,位于指令的最高4位[31:28]。
条件码共有16种,每种条件码用2个字符表示,这两个字符可以添加至指令助记符的后面,与指令同时使用。
当指令的执行条件满足时,指令才被执行,否则指令被忽略。如果在指令后不写条件码,则使用默认条件AL(无条件执行)。
指令的条件码
条 件 码 助记符后缀 标 志 含 义
0000 EQ Z置位 相等equal
0001 NE Z清零 不相等not equal
0010 CS C置位 无符号数大于或等于Carry Set
0011 CC C清零 无符号数小于
0100 MI N置位 负数minus
0101 PL N清零 正数或零plus
0110 VS V置位 溢出
0111 VC V清零 没有溢出
1000 HI C置位Z清零 无符号数大于high
1001 LS Z置位C清零 无符号数小于或等于less
1010 GE N等于V 带符号数大于或等于
1011 LT N不等于V 带符号数小于least
1100 GT Z清零且(N等于V) 带符号数大于great
1101 LE Z清零或(N不等于V) 带符号数小于或等于
1110 AL 忽略 无条件执行all
1111
条件码应用举例:
例:比较两个值大小,并进行相应加1处理,C语言代码为:
if ( a > b ) a++;
else b++;
对应的ARM指令如下(其中R0中保存a 的值,R1中保存b的值):
CMP R0, R1 ; R0与R1比较,做R0-R1的操作
ADDHI R0, R0, #1 ;若R0 > R1, 则R0 = R0 + 1
ADDLS R1, R1, #1 ; 若R0 <= R1, 则R1 = R1 + 1
CMP比较指令,用于把一个寄存器的内容和另一个寄存器的内容或一个立即数进行比较,同时更新CPSR中条件标志位的值。指令将第一操作数减去第二操作数,但不存储结果,只更改条件标志位。
CMP R1, R0 ;做R1-R0的操作。
CMP R1,#10 ;做R1-10的操作。
3)S项(sign)
S项是条件码设置项,它决定本次指令执行的结果是否影响至CPSR寄存器的相应状态位的值。该项是可选的,使用时影响CPSR,否则不影响CPSR。
4)Rd项(destination)
Rd是指令中的目标寄存器,它是必需的。根据指令的不同,有些指令中要求Rd必须有R0~R7之间,有些要求Rd必须在R0~R14之间,有些则没有特殊要求。
5)Rn项
Rn是第一个操作数的寄存器,和Rd一样,不同的指令对其的使用有不同的要求。
6)Opcode2项
Opcode2项是第二个操作数,在ARM指令中,该操作数有三种形式:立即数形式、寄存器Rm形式和寄存器加移位形式(Rm, shift)。
SUB R3, R1, #10
SUB R3, R1, R2
SUB R3, R1, R2, LSL #2
SUB R3, R1, R2, LSL R0
ARM指令详解
ARM指令集可分为以下6类:
1.跳转指令
2.数据处理指令
3.程序状态寄存器(PSR)处理指令
4.加载/存储指令
5.协处理器指令
6.异常产生指令
一、跳转指令
用于实现程序流程的跳转,在ARM程序中有两种方法可以实现程序流程的跳转:
1)、是使用专门的跳转指令,
2)、是直接向程序计数器PC写入跳转地址值。
第二种方法可以实现在4GB的地址空间中的任意跳转,
在跳转之前结合使用 MOV LR , PC 等类似指令,可以保存将来的返回地址值,
从而实现在4GB连续的线性地址空间的子程序调用。
ARM指令集中的跳转指令可以完成从当前指令向前或向后的32MB的地址空间的跳转,包括以下4条指令:
B 跳转指令
BL 带返回的跳转指令
BX 带状态切换的跳转指令
BLX 带返回和状态切换的跳转指令
B 指令的格式为:
B{条件} 目标地址
B指令是最简单的跳转指令。一旦遇到一个B 指令,ARM 处理器将立即跳转到给定的目标地址,从那里继续执行。
B Label程序无条件跳转到标号Label处执行
CMP R1, #0
BEQ Label
当CPSR寄存器中的Z条件码置位时,程序跳转到标号Label处执行。
BL指令的格式为:
BL{条件} 目标地址
BL 是另一个跳转指令,但跳转之前,会在寄存器R14中保存PC当前值,因此,可以通过将R14 的内容重新加载到PC中,
来返回到跳转指令之后的那个指令处执行。该指令是实现子程序调用的一个基本但常用的手段。
BL Label 当程序无条件跳转到标号Label处执行时,同时将当前的PC值保存到R14中
BX指令的格式为:
BX{条件} 目标地址
BX指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM指令,也可以是Thumb指令。
BX指令中所指定的目标地址,只能使用寄存器的寻址方式,即跳转的目标地址应先保存在一个寄存器中。
指令在实现跳转的同时,完成处理器的工作状态的切换(ARM状态与Thumb状态间的切换)。
BX指令中,用寄存器的最低位来指示切换到哪一个工作状态。
如寄存器最低位为1,则把目标地址处的代码解释为Thumb代码,进入Thumb工作状态,并自动将CPSR中的控制位T置1。
若寄存器最低位为0,则把目标地址处的代码解释为ARM代码,进入ARM工作状态,并自动将CPSR中的控制位T置0。
BLX指令的格式为:
BLX 目标地址
BLX指令 从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态有ARM状态切换到Thumb状态,该指令同时将PC的当前内容保存到寄存器R14中。
因此,当子程序使用Thumb指令集,而调用者使用ARM指令集时,可以通过BLX指令实现子程序的调用和处理器工作状态的切换。
同时,子程序的返回可以通过将寄存器R14值复制到PC中来完成。
ADRL R0, ThumbFun + 1 ;生成分支地址并置最低位为 1
BX R0 ;跳转到R0所指定的地址,并切换处理器到Thumb工作状态
...
ThumbFun
... ;Thumb汇编指令
二、数据处理指令
数据处理指令可分为数据传送指令、算术逻辑运算指令、比较指令等。
数据传送指令用于在寄存器和存储器之间进行数据的双向传输。
算术逻辑运算指令完成常用的算术与逻辑的运算,该类指令不但将运算结果保存在目的寄存器中,同时更新CPSR中的相应条件标志位。
1)数据传送指令(MOV、MVN)
MOV指令的格式为:
MOV{条件}{S} 目的寄存器,源操作数
MOV指令完成从另一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器。
其中S选项决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。
指令示例:
MOV R1, R0 ;将寄存器R0的值传送到寄存器R1
MOV PC, R14 ;将寄存器R14的值传送到PC,常用于子程序返回
MOV R1, R0, LSL#3 ;将寄存器R0的值左移3位后传送到R1
MVN指令的格式为:
MVN{条件}{S} 目的寄存器,源操作数
MVN指令可完成从另一个寄存器、被移位的寄存器、或将一个立即数加载到目的寄存器。
与MOV指令不同之处是在传送之前按位被取反了,即把一个被取反的值传送到目的寄存器中。
其中S决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。
MVN R0,#0xff ;R0 <--- 0xffffff00
MVN R1, R2
MOV PC, R14 ;将寄存器R14的值传送给PC,用于子程序返回。
2)数据比较指令(CMP、CMN、TST、TEQ)
CMP{条件} 操作数1,操作数2
CMP指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行比较,同时更新CPSR中条件标志位的值。
该指令进行一次减法运算,但不存储结果,只更改条件标志位。
标志位表示的是操作数1与操作数2的关系(大、小、相等),例如,当操作数1大于操作操作数2,则此后的有GT 后缀的指令将可以执行。
指令示例:
CMP R1, R0 ;将寄存器R1的值与寄存器R0的值相减,并根据结果设置CPSR的标志位
CMP R1,#100 ;将寄存器R1的值与立即数100相减,并根据结果设置CPSR的标志位
CMN{条件} 操作数1,操作数2
CMN 指令用于把一个寄存器的内容和另一个寄存器的内容或立即数取反后进行比较操作,根据运算结果影响CPSR中的标志位。
该指令实际完成操作数1和操作数2相加,并根据结果更改条件标志位。
TST{条件} 操作数1,操作数2
TST指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的与运算,并根据运算结果更新CPSR中条件标志位的值。
操作数1是要测试的数据,而操作数2是一个位掩码,根据测试结果设置相应标志位。
当位与结果为0时,EQ位被设置。该指令一般用来检测是否设置了特定的位。
TST指令通常和EQ、NE条件码配合使用,当所有测试位为0时,EQ有效,而只要有一个测试位不为0,则NE有效。
指令示例:
TST R1, #%1 ;用于测试在寄存器R1中是否设置了最低位(%表示二进制数)。
TST R0, #0X0000 0040 ;指令用来测试R0的位3是否为1。
TEQ{条件} 操作数1,操作数2
TEQ相等测试指令,用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的异或运算,并根据运算结果更新CPSR中的条件标志位。
指令用于比较两个操作数是否相等。如果相等,则 Z = 1,否则Z = 0。
指令通常和EQ、NE条件码配合使用
3)算术运算类指令(ADD、ADC、SUB、SBC、RSB、RSC)
算术运算类指令 {条件} {S} 目的寄存器,操作数1,操作数2
目的寄存器,操作数1和操作数2使用的寄存器必须在R0~R7之间。
操作数1应该是一个寄存器,操作数2可以是一个寄存器、被移位的寄存器或一个立即数。
ADD指令完成的功能是将操作数1加上操作数2,结果送到目的寄存器。
ADC指令完成的功能是将操作数1加上操作数2,再加上标志位C的值,结果送到目的寄存器。
SUB指令完成的功能是将操作数1减去操作数2,结果送到目的寄存器。
SBC指令完成的功能是将操作数1减去操作数2,再减去标志位C的取反值,结果送到目的寄存器。
RSB逆向减法指令完成的功能是将操作数2减去操作数1,结果送到目的寄存器。
RSC带借位的逆向减法指令完成的功能是将操作数2减去操作数1,再减去标志位C的取反值,结果送到目的寄存器。
ADD{条件}{S} 目的寄存器,操作数1,操作数2
ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。
操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
指令示例:
ADD R0, R1, R2 ;R0 = R1 + R2
ADD R0, R1, #256 ;R0 = R1 + 256
ADD R0, R2, R3, LSL#1 ;R0 = R2 + (R3 << 1)
SUB{条件}{S} 目的寄存器,操作数1,操作数2
SUB指令用于把操作数1减去操作数2,并将结果存放到目的寄存器中。
操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
SUB R0, R1, R2 ;R0 = R1 - R2
SUB R0, R1, #256 ;R0 = R1 - 256
SUB R0, R2, R3, LSL#1 ;R0 = R2 - (R3 << 1)
ADDS R1, R1, #10 ;结果影响标志位
ADD R1, R1, R2 ;结果不影响标志位
ADD R3, R1, R2, LSL #2 ; R3 = R1 + ( R2 << 2 )
SUB R0, R1, #256 ;R0 = R1 - 256 , 结果不影响标志位
SUBS R0, R2, R3, LSL #1 ;R0 = R2 - ( R3 <<1 ),结果影响标志位
SUB SP, #380 ;SP = SP - 380
SBC R0, R1, R2 ;R0 = R1 - R2 - !C
RSC R0, R1, R2 ;R0 = R2 - R1 - !C
4)逻辑运算类指令(AND、ORR、EOR、BIC)
AND{条件}{S} 目的寄存器,操作数1,操作数2
AND指令用于在两个操作数上进行逻辑与运算,并把结果放置到目的寄存器中。
操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
该指令常用于屏蔽操作数1的某些位。
S选项,说明运算结果影响CPSR的条件标志位,没有S选项,则不影响CPSR的条件标志位。
AND R0, R0, #3 ;该指令保持R0的0、1位,其余位清零。
ORR{条件}{S} 目的寄存器,操作数1,操作数2
ORR指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中。
操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
该指令常用于设置操作数1的某些位。
ORR R0, R0, #3 ;该指令设置R0的0、1位,其余位保持不变。
EOR{条件}{S} 目的寄存器,操作数1,操作数2
EOR(异或)指令常用于将操作数1的某个位取反。与0相异或,保持不变,与1相异或,则取反。
BIC{cond}{S} Rd, Rn, operand2
BIC指令用于清除Rn 中的某些位,并把结果存放在Rd中,操作数operand2 为32位的掩码,如果掩码中设置了某一位为1,则清除这一位。未设置的掩码位保持不变。
BIC R0, R0, #%1011 ;将R0的0,1,3位清零,其余位不变。
5)乘法指令与乘加指令
ARM微处理器支持的乘法指令与乘加指令共有6条,可分为运算结果为32位和结果为64位两类,与前面的数据处理指令不同,
指令中的所有操作数、目的寄存器必须为通用寄存器,不能对操作数使用立即数或被移位的寄存器,
同时,目的寄存器和操作数1必须是不同的寄存器。
MUL{条件}{S} 目的寄存器,操作数1,操作数2
目的寄存器 = 操作数1 × 操作数2,同时可以根据运算结果设置CPSR中相应的条件标志位N和Z。
MUL指令完成将操作数1与操作数2的乘法运算,并把结果放置到目的寄存器中,同时可以根据运算结果设置CPSR中相应的条件标志位。
其中,操作数1和操作数2均为32位的有符号数或无符号数。
MUL R0, R1, R2 ;R0 = R1 × R2
MULS R0, R1, R2 ;R0 = R1 × R2,同时设置CPSR中的相关条件标志位
MLA {条件} {S} 目的寄存器,操作数1, 操作数2, 操作数3
目的寄存器 = 操作数1 × 操作数2 + 操作数3,同时可以根据运算结果设置CPSR中相应的条件标志位N和Z。
操作数1和操作数2均为32位的有符号数或无符号数。
SMULL指令(S:Signed, 有符号)
SMULL {条件} {S} 目的寄存器Low,目的寄存器High,操作数1, 操作数2
目的寄存器Low = (操作数1 × 操作数2 )的低32位,
目的寄存器High = (操作数1 × 操作数2 )的高32位,同时可以根据运算结果设置CPSR中相应的条件标志位。
操作数1和操作数2均为32位的有符号数。
SMULL R0, R1, R2, R3 ;R0 = (R2 ×R3)的低32位, R1 = (R2 ×R3)的高32位。
SMLAL指令(S:Signed, 有符号)
SMLAL {条件} {S} 目的寄存器Low,目的寄存器High,操作数1, 操作数2
目的寄存器Low = (操作数1 × 操作数2 )的低32位 + 目的寄存器Low,
目的寄存器High = (操作数1 × 操作数2 )的高32位 + 目的寄存器High,同时可以根据运算结果设置CPSR中相应的条件标志位。
操作数1和操作数2均为32位的有符号数。
SMLAL R0, R1, R2, R3 ;R0 = (R2 ×R3)的低32位 + R0,
;R1 = (R2 ×R3)的高32位 + R1。
UMULL指令(U:UnSigned, 无符号)
UMULL {条件} {S} 目的寄存器Low,目的寄存器High,操作数1, 操作数2
目的寄存器Low = (操作数1 × 操作数2 )的低32位,
目的寄存器High = (操作数1 × 操作数2 )的高32位,同时可以根据运算结果设置CPSR中相应的条件标志位。
操作数1和操作数2均为32位的无符号数。
UMULL R0, R1, R2, R3 ;R0 = (R2 ×R3)的低32位, R1 = (R2 ×R3)的高32位。
UMLAL指令(U:UnSigned, 无符号)
UMLAL {条件} {S} 目的寄存器Low,目的寄存器High,操作数1, 操作数2
目的寄存器Low = (操作数1 × 操作数2 )的低32位 + 目的寄存器Low,
目的寄存器High = (操作数1 × 操作数2 )的高32位 + 目的寄存器High,同时可以根据运算结果设置CPSR中相应的条件标志位。
操作数1和操作数2均为32位的无符号数。
UMLAL R0, R1, R2, R3
;R0 = (R2 ×R3)的低32位 + R0,
;R1 = (R2 ×R3)的高32位 + R1。
三、程序状态寄存器访问指令
ARM微处理器支持程序状态寄存器访问指令,用于在程序状态寄存器和通用寄存器之间传送数据。
MRS {条件} 通用寄存器, 程序状态寄存器(CPSR、SPSR)
将状态寄存器的内容传送到通用寄存器。
使用环境:
1)当需要改变程序状态寄存器的内容时,可用MRS将状态寄存器的内容读入到通用寄存器,修改后再写回到程序状态寄存器。
2)当在异常处理或进程切换时,需要保存程序状态寄存器的值,可先用该指令读出程序状态寄存器的值,然后保存。
MSR {条件} 程序状态寄存器(CPSR、SPSR)_<域>,操作数
将操作数的内容传送到程序状态寄存器的特定域中。其中,操作数可以为通用寄存器或立即数。
<域>用于设置程序状态寄存器中需要操作的位,32位的程序状态寄存器分为4个域:
f域:位31~位24为条件标志位域;
s域:位23~位16为状态位域;
x域:位15~位8为扩展位域;
c域:位7~位0为控制位域;
该指令通常用于恢复或改变程序状态寄存器的内容,在使用时,一般要在MSR指令中指明将要操作的域。
使用环境:
1)当需要改变程序状态寄存器的内容时,可用MRS将状态寄存器的内容读入到通用寄存器,修改后再写回到程序状态寄存器。
2)当在异常处理或进程切换时,需要保存程序状态寄存器的值,可先用该指令读出程序状态寄存器的值,然后保存。
MSR CPSR, R0 ;CPSR←R0
MSR SPSR_c, R0 ;传送R0到SPSR,但仅修改SPSR中的控制位域
MSR CPSR_c, #0XD3 ; CPSR[7..0] = 0XD3 , 即切换到管理模式
MSR CPSR_cxsf, R3 ; CPSR ← R3
注意:只有在特权模式下,才能修改状态寄存器。
程序中不能通过MSR指令直接修改CPSR中的T控制位来实现ARM/Thumb状态的切换,必须使用BX指令来完成处理器状态的切换。
MRS与MSR配合使用,可以实现CPSR或SPSR寄存器的读/修改/写操作,进行处理器模式 切换,进行允许/禁止IRQ/FIQ中断等的设置。
例:使能IRQ中断
MRS R0, CPSR
BIC R0, R0, #0X80
MSR CPSR_c, R0
MOV PC, LR
例:禁止IRQ中断
MRS R0, CPSR
ORR R0, R0, #0X80
MSR CPSR_c, R0
MOV PC, LR
四、存储器加载/存储指令
用于在寄存器和存储器之间传送数据,加载指令用于将存储器中的数据传送到寄存器,存储指令则将寄存器中的数据传送到存储器。
存储器加载/存储指令分为单个存储器加载/存储指令和多个存储器加载/存储指令。
1)单个存储器加载/存储指令
LDR字数据加载指令;
LDRH(Half)半字数据加载指令;
LDRB字节数据加载指令;
STR字数据存储指令;
STRH半字数据存储指令;
STRB字节数据存储指令。
加载指令
加载指令 {条件} 目的寄存器, <存储器地址>
LDR R0, [R1] ;将地址为R1的字数据读入R0。
LDR R0, [R1, R2] ;将地址为R1+R2的字数据读入R0。
LDR R0, [R1, #4] ;将地址为R1+4的字数据读入R0。
LDR R0, [R1, R2]! ;将地址为R1+R2的字数据读入R0,并将新地址R1+R2写入R1。
LDR R0, [R1, R2, LSL #2 ]! ;将地址为R1 + R2 × 4的字数据读入R0,并将新地址R1 + R2 × 4写入R1。
LDRH指令用于从存储器中将一个16位的半字数据传送到目的寄存器中,同时将寄存器的高16位清零。
LDRH R0, [R1] ;将地址为R1的半字数据读入R0,并将R0的高16位清零。
LDRB指令用于从存储器中将一个8位的字节数据传送到目的寄存器中,同时将寄存器的高24位清零。
LDRB R0, [R1] ;将地址为R1的字节数据读入R0,并将R0的高24位清零。
注意:当是字操作时,操作数的地址必须是字对齐的,如果是半字操作,操作数的地址必须是半字对齐。否则,读出的数据是无效,随机的。
LDR R0, [R1, # 2]
LDRH R0, [R1, # 1]
存储指令
存储指令 {条件} 源寄存器, <存储器地址>
STR R0, [R1], #8 ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。
STR R0, [R1 , #8] ;将R0中的字数据写入以R1+8为地址的存储器中。
STRH指令用于从源寄存器中将一个16位的半字数据传送到存储器中。该半字数据为源寄存器中的低16位。
STRH R0, [R1, #8] ;将寄存器R0中的低16位写入以R1 + 8为地址的存储器中。
STRB指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。
注意:当是字操作时,操作的地址必须是字对齐的,如果是半字操作,操作的地址必须是半字对齐。否则,读出的数据是无效,随机的。
2)批量数据加载/存储指令
可以一次在一片连续的存储器单元和多个寄存器之间传送数据,批量加载指令用于将一片连续的存储器中的数据传送到多个寄存器,批量数据存储指令完成相反的操作。
LDM(或STM)指令(Load Data To Multiple Register)
LDM(或STM) {条件} {类型} 基址寄存器{!} ,寄存器列表{^}
{类型}为以下几种情况:
类 型 含 义
IA 每次操作后,地址加4
IB 每次操作前,地址加4
DA 每次操作后,地址减4
DB 每次操作前,地址减4
FD 满递减堆栈
ED 空递减堆栈
FA 满递增堆栈
EA 空递增堆栈
{!}为可选后缀,若选用,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。
基址寄存器不允许为R15,寄存器列表可以为R0 ~ R15的任意组合。
{^}为可选后缀,当指令为LDM且寄存器列表中包含有R15,选用该后缀表示:除了正常的数据传送之外,还将SPSR复制到CPSR。同时,该后缀还表示传入或付传出的是用户模式下的寄存器,而不是当前模式下的寄存器。
例:
STMFD SP!, {R0 - R7 , LR} ;现场保存,将R0 - R7 , LR入栈,满递减堆栈。
LDMFD SP!, {R0 - R7 , PC}^ ;恢复现场,异常处理返回,满递减堆栈
在进行数据复制时,先设置好源数据指针,然后使用块拷贝寻址指令进行读取和存储。而在堆栈操作中,则要先设置堆栈指针SP,然后使用堆栈寻址指令实现堆栈操作。
五、数据交换指令
支持在存储器和寄存器之间交换数据。
SWP ((Swap)字数据交换指令;
SWPB 字节数据交换指令。
交换指令 {条件} 目的寄存器, 源寄存器1, [源寄存器2]
SWP R0, R1, [R2] ;将R2所指的存储器中的字数据传送到R0,同时将R1中的字数据传送到R2所指的存储器单元。
显然,当源寄存器1与目的寄存器是同一个寄存器时,就完成了寄存器与存储器间的交换操作。
SWPB指令用于将源寄存器2所指向的存储器中的字节数据到目的寄存器中,目的寄存器的高24位清零,同时将源寄存器1中的低8位数据(低位字节)传送到源寄存器2所指向的存储器中。
六、异常产生指令
异常指令有两条:SWI软件中断指令和BKPT断点中断指令。
SWI {条件} 24位的立即数
产生软件中断,方便用户程序调用操作系统的系统例程。
切换运行模式到管理模式,设置PC来执行在地址0X08处的下一条指令,设置相应的R13_svc和R14_svc。该指令的操作与执行BL 0X08这条指令的效果是相同的。不同的地方在于,SWI还带有指明系统例程的类型的“24位的立即数”。在具体应用中,为便于记忆,可以使用字符串代替“24位的立即数”,例如:SWI “OS_Write0”和 SWI 0X02是一样的。当指令中24位的立即数被忽略时,系统例程的类型由通用寄存器R0的内容决定。传送给系统例程的参数通过通用寄存器来传递。
BKPT 16位的立即数
用于产生软件断点中断,执行时中断正常指令,进入相应的调试子程序。
七、协处理器指令
ARM处理器可支持多达16个协处理器,每个协处理器只执行针对其自身的协处理指令。
ARM的协处理器指令主要用于ARM处理器初始化、协处理器的数据处理操作、在ARM处理器与协处理器的寄存器之间传送数据、在协处理器和存储器之间传送数据。
ARM协处理器指令有以下5条:
1)CDP协处理器数据操作指令;
2)LDC协处理器数据加载指令;
3)STC协处理器数据存储指令;
4)MCR ARM处理器寄存器到协处理器寄存器的数据传送指令;
5)MRC 协处理器寄存器到ARM处理器寄存器的数据传送指令。
1)CDP指令
CDP {条件}协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2
用于ARM处理器通知协处理器执行特定的操作,若协处理器不能执行指定的操作,则产生未定义指令异常。
注意:指令中涉及到的寄存器都是协处理器的寄存器,不涉及ARM处理器的寄存器和存储器。操作码1、操作码2是协处理器要执行的操作。
CDP p5, 1, c3, c4, c5, 2
;指示协处理器P5,执行操作1,可选操作为2;C3, C4, C5是相应的协处理器寄存器。
2)LDC指令
LDC {条件}{L}协处理器编码,目的寄存器,[源寄存器]
用于将源寄存器所指向的存储器中的字数据传送到目的寄存器中。若协处理器不能成功执行,则产生未定义指令异常。选项{L}表示指令为长读取操作,可用于双精度数据的传输。
注意:指令中涉及到的源寄存器是ARM处理器的寄存器。
LDC P3, C4, [R2, #4]
3) STC指令
STC {条件}{L}协处理器编码,源寄存器,[目的寄存器]
用于将源寄存器中的字数据传送到目的寄存器所指向的存储器中。若协处理器不能成功执行,则产生未定义指令异常。选项{L}表示指令为长读取操作,可用于双精度数据的传输。
注意:指令中涉及到的目的寄存器是ARM处理器的寄存器。
STC P3, C4, [R0]
;将协处理器P3的寄存器C4中的数据传送到ARM处理器的寄存器R0所指向的存储器.
4)MCR指令
MCR {条件} 协处理器编码,协处理器操作码1,源寄存器,目的寄存器1,目的寄存器2,协处理器操作码2
MCR指令用于将ARM处理器寄存器中的数据传送到协处理器的寄存器中。若协处理器不能完成这个操作,将引发未定义指令异常。源寄存器为ARM处理器的寄存器。
5)MRC指令
MRC {条件}协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理器操作码2
MRC指令用于将协处理器寄存器中的数送到ARM处理器的寄存器中。若协处理器不能完成这个操作,将引发未定义指令异常。源寄存器为ARM处理器的寄存器。
MRC P3 , 3 , R0 , C4 , C5 , 6
;将协处理器P3的寄存器C4与C5中的数据传送到ARM的寄存器中,并执行编号为3和6的操作。
Thumb指令集合
Thumb指令集是ARM指令集的一个子集,允许指令编码为16位的长度,Thumb指令集在保留32位代码优势的同时,大大节省了系统的存储空间。
当处理器在执行ARM程序段时,称ARM处理器处于ARM工作状态,当处理器在执行Thumb程序段时,称ARM处理器处于Thumb工作状态。
在编写Thumb指令时,先要用伪指令CODE16声明以下为Thumb指令代码,在ARM指令代码中可以使用BX指令跳转到Thumb指令代码片。同样编写ARM代码时,则使用伪指令CODE32进行声明,在Thumb指令代码中使用BX指令可以跳转到ARM指令代码处。
大多数Thumb指令是无条件执行的,而几乎所有的ARM指令都是有条件执行的。由于Thumb数据处理指令中的目的寄存器与其中的一个源寄存器相同,Thumb指令在指令编码时由三个操作数改为两个操作数。
通常实现同样的程序功能时,所需的Thumb指令的条数比ARM指令多。但使用Thumb指令集合的代码有以下特点:
1)比ARM代码更节略存储空间。
2)使用的指令条数比ARM代码多。
3)若使用32位的存储器,ARM代码比Thumb代码快约40%。
4)若使用16位的存储器,Thumb代码比ARM代码快约40%~50%。
5)与ARM代码相比较,使用Thumb代码,存储器的功耗会降低约30%。