ARM指令集
一、ARM指令的格式和分类
经典ARM指令格式如下:
<opcode> {<cond>} {S} <Rd>,<Rn>,<operand2>
- <> 为必选项,{}为可选项
- 为操作码,如ADD表示算术加操作指令
- {} 决定指令执行条件域
- {S} 决定指令执行是否影响CPSR寄存器的值
- 为目的寄存器
- 的第一个操作数为寄存器
- 为第二个操作数
二、ARM指令条件执行及标志位
-
ARM指令可以通过添加适当的条件码后缀来达到条件执行的目的
这样可以提高代码密度,减少分支跳转指令数目,提高性能。 -
默认情况下,数据处理指令不影响条件码标志位,但可以选择通过添加“S”来影响标志位
CMP不需要增加 “S”就可改变相应的标志位。 -
使用条件码可以实现高效的逻辑操作,节省跳转和条件语句,提高代码效率
如果指令不标明条件码,将默认为无条件(AL)执行。 -
条件码表
三、跳转指令
跳转指令用于实现程序流程的跳转,在ARM程序中有两种方法可以实现程序的跳转,一种是使用跳转指令直接跳转,另一种是直接向PC寄存器赋值实现跳转。
-
B{条件} 目标地址
B指令最简单的跳转指令,一旦遇到一个B指令,ARM处理器立即跳转至给定的目标地址,由此处继续执行。跳转指令B限制在当前指令的土32MB范围内 -
BL{条件} 目标地址
BL是一另个跳转指令,在跳转前会将下一条指令的地址复制到R14中,然后跳转到指定的地址运行程序。可以通过将R14的内容重新加载到PC中,并返回到跳转指令之后的那个指令处执行。 BL是实现子程序调用的一个基本但常用的手段。 -
BLX{条件} 目标地址
BLX指令从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM状态切换到Thumb状态,该指令同时将PC的当前内容到寄存器R14中。当程序使用Thumb指令集,而调用者使用ARM指令集时,可以通过BLX指令实现程序的调用和处理器工作状态的切换。子程序的返回可以通过将寄存器R14复制到PC中来完成。 -
BX{条件} 目标地址
BX指令是带状态切换的跳转指令,跳转到指定的目标地址执行程序。若目标地址寄存器的[0]位为1,则跳转时自动将CPSR中的标志T置位,即把目标地址的代码解释为Thumb指令。若目标地址寄存器的[0]位为0,则跳转时自动将CPSR中的标志T复位,即把目标地址的代码解释为ARM指令。
四、数据处理指令
- MOV{条件} {S} 目的寄存器,源操作数
MOV指令可以完成的功能包括:- 数据从一个寄存器到另一个寄存器的传输
- 将常数传送到寄存器中
- 实现移位操作,左移位可以实现将操作数乘以2^n
- 当PC寄存器作为目标寄存器时可以实现程序的跳转
- 当PC寄存器作为目标寄存器且指令中S位被设置时,指令在执行跳转操作的同时,将当前处理器模式的处理器模式的SPSR寄存器内容复制到CPSR中
MOV R0,R1
MOVS R1,R3,LSL,#3
MOV PC,LR
- MVN{条件} {} 目的寄存器,源操作数
MVN指令可完成从另一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器。与MOV指令不同之处是在传送之前按位被取反了,即把一个被取反的值传送到目的寄存器中。其中S决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。因为其具有取反功能,所以可以装载范围更广的立即数。
MVN R1,#0xFF
MVN R1,R2
MVN R0,#0
- ADD{条件} {S} 目的寄存器,操作数1,操作数2
ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中,同时根据操作的结果更新CPSR中相应的条件标志位
ADDS R1,R1,#1
ADD R1,R1,R2
ADD R0,R2,R3,LSL,#1
- SUB{条件} {S} 目的寄存器,操作数1,操作数2
SUB指令用于把操作数1减去操作数2,并将结果存放在目的寄存器中,同时根据操作的结果更新CPSR中相应的条件标志位。该指令可用于有符号数或无符号数据减法运算。
SUB R0,R0,#1
SUBS R0,R1,R2
SUB R0,R2,R3,LSL,#1
- RSB{条件} {S} 目的寄存器,操作数1,操作数2
RSB指令称为逆向减法指令,用于把操作数2,减去操作数1,并将结果存放到目的寄存器中,同时根据操作的结果更新CPSP中相应的条件标志位。该指令可用于有符号数或无符号数据减法运算。
RSB R3,R1,#0xFF00
RSB R0,R2,R3,LSL,#1
RSB R0,R1,#0
- ADC{条件} {S} 目的寄存器,操作数1,操作数2
ADC指令用于把两个操作数相加,再加上CPSR中的C条件标志位的值,并将结果存放到目的寄存器中。同时根据操作的结果更新CPSR中相应的条件标志位。它使用一个进位标志位,这样就可以做比32位大的数据加法,注意不要忘记S后缀来更改进位标志。操作数1应是一个寄存器,操作数2可以是寄存器、被移位的寄存器或一个立即数。
ADDS R0,R0,R2
ADC R1,R2,R3
- SBC{条件} {S} 目的寄存器,操作数1,操作数2
SBC指令用于把操作数1减去操作数2,再减去CPSR中的C条件标志位的反码,然后将结点存放到目的寄存器中。同时根据操作的结果更新CPSR中相应的条件标志位。该指令使用进位标志来表示借位,这样就可以做大于32位的减法。注意不要忘记设置S后缀来更改进位标志,该指令可用于有符号数或无符号数据减法运算。
SUBS R0,R0,R2
SUB R1,R1,R3
- RSC{条件} {S} 目的寄存器,操作数1,操作数2
RSC指令用于把操作数2减去操作数1,再减去CPSR中的C条件标志位的反码,并将结果存放到目的寄存器中。同时根据操作的结果更新CPSR中相应的条件标志位。该指令使用进位标志来表示借位,这样就可以做大于32位的减法。注意不要忘记设置S后缀来更改进位标志,该指令可用于有符号数或无符号数据减法运算。
RSBS R2,R0,#0
RSC R3,R1,#0
RSC R0,R1,R2
- AND{条件} {S} 目的寄存器,操作数1,操作数2
AND指令用在两个操作数上进行逻辑与运算,并把结果存放到目的寄存器中。同时根据操作的结果更新CPSR中相应的条件标志位,该指令学用于屏蔽操作数1的某些位。
AND R0,R0,#3
AND R2,R1,R3
- ORR{条件} {S} 目的寄存器,操作数1,操作数2
ORR指令用在两个操作数上进行逻辑或运算,并把结果旋转到目的寄存器中。同时根据操作的结果更新CPSR中相应的条件标志位,该指令常用于设置操作数1的的某些位。
ORR R0,R0,#3
MOV R1,R2,LSR,#4
ORR R3,R1,R3,LSL,#4
- EOR{条件} {S} 目的寄存器,操作数1,操作数2
EOR指令用在两个操作数上进行逻辑异或运算,并把结果放置到目的寄存器中。同时根据操作的结果更新CPSR中相应的条件标志位,该指令常用于反转操作数1的某些位。
EOR R1,R1,#0x0F
EOR R2,R1,R0
EORS R0,R5,#0x01
- BIC{条件} {S} 目的寄存器,操作数1,操作数2
BIC指令用于清除操作数1的某些位,并把结果放置到目的寄存器中。同时根据操作的结果更新CPSR中相应的条件标志位。操作数2为32位的掩码,如果在掩码中设置了某一位,则清除这一位,未设置掩码位保持不变。
BIC R0,R0,#%1011
BIC R1,R1,#0x0F
BIC R1,R2,R3
-
CMP{条件} 操作数1,操作数2
CMP指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行比较,同时更新CPSR中的条件标志位的值。该指令进行一次减法运算,但不存储结果,只更改条件标志位,标志位表示的是操作数1与操作数2的关系。如果操作数1大于操作数2,则此后GT后缀的指令将执行,不需显示的指定S后缀更改状态标志,如果指定了则忽略。 -
CMN{条件} 操作数1,操作数2
CMN指令用于把一个寄存器的内容和另一个寄存器的内容或立即数据取反后进行比较。同时更新CPSR中条件标志位的值,该指令实际完成操作数1和操作数2相加,并根据结果更改条件标志位。CMN指令与ADD指令的区别在于CMN指令不保存运算结果。
CMN R1,R0
CMN R1,#100
- TST{条件} 操作数1,操作数2
TST指令用于把操作数1的内容和操作数的内容进行按位与运算,并根据运算结果更新CPSR中条件标志位的值。操作数1是要测试的数据,而操作数2是一个位掩码,该指令一般用来检测是否设置了特定的位。
TST R0,#0x01
TST R0,#0x0F
- TEQ{条件} 操作数1,操作数2
TEQ指令用于把操作数1的内容和操作数的内容进行按位异或运算,并根据运算结果更新CPSR中条件标志位的值。该指令通常用于比较操作数1和操作数2是否相等。
TEQ R1,R2
五、程序状态寄存器传输指令
ARM指令有两条指令用于状态寄存器和通用寄存器之间传送数。修改寄存器一般是通过 “读取-修改-写回” 三个步骤的操作来实现的。这两指令分别是状态寄存器到通用寄存器的传送指令MRS,通用寄存器到状态寄存器的传送指令MSR。
- MRS{条件} 通用寄存器,程序状态寄存器
当异常中断允许被嵌套时,需要在进入异常中断后嵌套中断发生之前的保存当前处理器对应的SPSR。在进程切换时也需要保存当前状态寄存器的值。
MRS R0,CPSR
MRS R0,SPSR
- MSR{条件} 程序状态寄存器_<域>,通用寄存器
当退出异常中断处理程序时,如果事先有保存状态寄存器的内容,通常使用MSR将事先保存的数据恢复到状态寄存器中。域用于设置程序状态寄存器中需要操作的位,32位的程序状态寄存器可分为4个域:- [31:24] 为条件标志位域,用f表示
- [23:16] 为状态位域,用s表示
- [15:8] 为扩展位域,用x表示
- [7:0] 为控制位域,用c表示
MSR CPSR_c,#0xD3
MSR CPSR_cxsf,R3
六、Load与Store指令
Load指令用于从内存中读取数据放入寄存器中,Store指令用于将寄存器中的数据保存到内存。
- LDR{条件} 目的寄存器,<存储器地址>
LDR指令用于从存储器中将一个32位的数据传送到目的寄存器中。当程序计数器PC作为目的寄存器时,指令从存储器中读取的数据被目的地址,从而实现程序流程的跳转。
LDR R0,#8
LDR R0,[R1,R2]
LDR R0,[R1,# 8]
- STR{条件} 源寄存器,<存储器地址>
STR指令用于从源寄存器中将一个32位数据传送到存储器中。
STR #8,R0
STR R0,[R1,#8]
- LDM/STM{条件} {类型} 基址寄存器,寄存器列表
LDM和STM可以实现在一组寄存器和一块连续的内存单元之间传输数据。LDM为加载多个寄存器,STM为存储多个寄存器。LDM、STM的主要用途是现场保存,数据复制,参数传递,其模式有8种:- 用于数据块传输
IA 每次传送后地址加4
IB 每次传送前地址加4
DA 每次传送后地址减4
DB 每次传送前地址减4 - 用于堆栈操作
FD 满递减堆栈
ED 空递减堆栈
FA 满递增堆栈
EA 空递增堆栈
- 用于数据块传输
STMFD R13,{R0,R4-R12,LR}
DMFD R13,{R0,R4-R12,LR}
- SWP {条件} 目的寄存器,源寄存器1,[源寄存器2]
SWP指令用于将源寄存器2中的把指向的存储器中的数据传送到目的寄存器中。同时将源寄存器1中的数据传送到源寄存器2所指向的存储器中。当源寄存器1和目的寄存器为同一寄存器时,指令将交换目的寄存器和存储器的内容。
7、异常中断产生指令
SWI,即software interrupt软件中断。该指令产生一个SWI异常。意思就是处理器模式改变为超级用户模式,CPSR寄器保存到超级用户模式下的SPSR寄存器,并且跳转到SWI向量。
指令格式如下:SWI{cond} immed_24
Cond域:是可选的条件码 (参见 ARM汇编指令条件执行详解).
immed_24域:范围从 0 到 224-1 的表达式, (即0-16777215)。用户程序可以使用该常数来进入不同的处理流程。