文章目录
ARM指令
指令分区
- ARM指令代码一般可以分为五个域
- 条件码域[31:28] ,4位条件码共有16种组合
- 指令代码域[27:20],除指令编码外、还包含几个很重要的指令特征位和可选后缀的编码
- 地址基址Rn域[19:16],4位可编码R0-R15共16个寄存器
- 目标或源寄存器Rd域[15:12],4位可编码R0-R15共16个寄存器
- 地址偏移或操作寄存器、操作数域[11:0]
指令可选后缀
S 后缀
- 含义:使用S后缀时,指令执行后程序状态寄存器的条件标志位将刷新;如:
ADDS R3,R5,R8
- 使用范围
- 有些指令不需要加S后缀,在执行时同样可以刷新条件标志位。如:CMP, TEQ, TST等。
- 有些指令不会引起条件标志位的变化,如:
STR R5, [R7]
- 在书写时,
S后缀紧跟在指令助记符后面
!后缀
- 含义:在指令的地址表达式中含有!后缀时,指令执行后,基址寄存器中的地址将发生变化(事先访问方式)
基址寄存器中的地址值 (指令执行后) =指令执行前的值+地址偏移量
- 位置和范围
- !后缀必须紧跟在表达地址的表达式后面,
而地址表达式要有明确的地址偏移量
!后缀不能用在R15的后面
- 当使用在单个地址寄存器后面时,
必须确信这个寄存器有隐性的偏移量
,如:STMDB R1!, {R3,R14}
- !后缀必须紧跟在表达地址的表达式后面,
B 后缀 / H 后缀
-
含义:
- B后缀的含义:指令所涉及的数据是一字节,不是一字或半字。
- H后缀的含义:指令所涉及的数据是二字节,不是一字。
-
位置
- B后缀紧跟在指令助记符后面。
- H后缀紧跟在指令助记符后面。
T 后缀
- 含义:指令在特权模式下对存储器的访问,将被存储器看成是用户模式的访问。
- 限制:
- 一般只用在字传送和无符号字节传送中
- 在用户模式下不可选用,选用是没有意义的
- 不能与事先更新寻址一起使用
条件后缀
- 被测试条件位有Z、C、N和V
- 在汇编语言中,条件码助记符紧接在指令助记符后面,如果既选条件后缀也选S后缀,则书写中“S”排列在后面。
- 条件后缀是要测试条件标志位,而S后缀是要刷新条件标志位
- 条件后缀要测试的是指令执行前的标志位,而S后缀是依据指令执行的结果改变条件标志
指令类型
跳转指令
实现跳转的两种方法
-
使用专门的跳转指令(短跳转,从当前指令向前或向后的
32MB
的地址空间的跳转)- B 跳转指令
- BL
带返回
的跳转指令(函数调用) - BX
带状态切换
的跳转指令 - BLX 带返回和状态切换的跳转指令
(ARM7不支持)
-
直接向程序计数器PC写入跳转地址值(长跳转,可以实现在
4GB
的地址空间中的任意跳转)
跳转指令的编码
- 存储在跳转指令中的实际值是相对当前PC值的一个
偏移量
,而不是一个绝对地址 - 处理器把偏移量(24 位有符号数)左移两位,进行
符号扩展
后再与PC相加。 左移两位
:机器字长32位,指令中给出的偏移量是按字(32位)寻址的,而PC寄存器的内容按字节(8位)寻址,也就是说假如给出的偏移量是0x0100,那么对应按字节寻址的地址就应该是0x0400,即按字寻址的偏移量的4倍,也就是左移2位,才能与PC内容相加。
B 指令
B{条件} 目标地址
- B指令是最简单的跳转指令。一旦遇到一个 B 指令,ARM 处理器将立即跳转到给定的目标地址,从那里继续执行。
BL 指令
BL{条件} 目标地址
- 该指令是实现子程序调用的一个基本而常用的手段:跳转之前,会
在寄存器R14中保存PC的当前内容(下一条指令)
,因此,可以通过将R14(LR) 的内容重新加载到PC中
,来返回到跳转指令之后的那个指令处执行。
条件跳转
BX指令
BX{条件} <Rm>
- BX指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM指令,也可以是Thumb指令。
- 目标地址处的指令类型由寄存器的bit[0]决定。
- 伪代码:
BLX 指令
BLX 目标地址
BLX 目标地址
指令从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM状态切换到Thumb状态
,该指令同时将PC的当前内容保存到寄存器R14中
。- 子程序的返回可以通过将寄存器R14值复制到PC中来完成。
- 从ARM到Thumb的状态切换,并可以通过BX R14返回。
BLX{条件} <Rm>
BLX{条件} <Rm>
指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM指令,也可以是Thumb指令。目标地址处的指令类型由寄存器<Rm>的bit[0]决定
。
子程序的返回方法
MOV PC, R14
BX R14
- 当子程序入口中使用了
STMFD R13!, {<registers>,R14}
时,可以用指令LDMFD R13!, {<registers>,PC}
返回
数据处理指令
<操作>{<cond>}{S} Rd, Rn, Operand2
- 比较指令影响标志位,不指定Rd
- 数据搬移不指定Rn
- 第二个操作数通过桶型移位器送到ALU中。
数据搬移
MOV 指令
MOV{条件}{S} 目的寄存器,源操作数
- MOV指令可完成从另一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器。
- 其中S选项决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。
当PC作为目标寄存器且指令中S位被置位时
,指令在执行跳转操作的同时,将当前处理器模式的SPSR内容复制到CPSR中。MOVS PC, LR
可以实现从某些异常中断中返回
- 指令示例
MOV R1,R0 ;将寄存器R0的值传送到寄存器R1
MOV PC,R14 ;将寄存器R14的值传送到PC,常用于子程序返回
MOV R1,R0,LSL#3 ;将寄存器R0的值左移3位后传送到R1
MOV R1,#123 ;将立即数123传送到R1
MVN 指令
MVN{条件}{S} 目的寄存器,源操作数
- MVN指令可完成从另一个寄存器、被移位的寄存器、或将一个立即数加载到目的寄存器。
- 与MOV指令不同之处是
在传送之前按位被取反了
,即把一个被取反的值
传送到目的寄存器中。
比较指令
CMP 指令
CMP{条件} 操作数1,操作数2
- CMP指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行
比较
,同时更新CPSR中条件标志位的值
。 - 该指令进行一次
减法
运算,但不存储结果
,只更改条件标志位。
- 指令示例
CMP R1,R0 ;将寄存器R1的值与寄存器R0的值相减,并根据结果设置CPSR的标志位
CMP R1,#100 ;将寄存器R1的值与立即数100相减,并根据结果设置CPSR的标志位
CMN 指令
CMN{条件} 操作数1,操作数2
- CMN指令用于
把一个寄存器的内容和另一个寄存器的内容或立即数取反后进行比较
,同时更新CPSR中条件标志位的值。 - 该指令实际完成操作数1和操作数2
相加
,并根据结果更改条件标志位。
- 指令示例
CMN R1,R0 ;将寄存器R1的值与寄存器R0的值相 加,并根据结果设置CPSR的标志位
CMN R1,#100 ;将寄存器R1的值与立即数100相 加,并根据结果设置CPSR的标志位
TST 指令
TST{条件} 操作数1,操作数2
- TST指令用于把一个寄存器的内容和另一个寄存器的内容或立即数
进行按位与运算
,并根据运算结果更新CPSR中条件标志位的值。 - 操作数1是要测试的数据,而操作数2是一个位掩码,该指令一般用来检测是否设置了特定的位。
TST指令用于测试寄存器中某些位是1还是0
- 指令示例
TST R1,#%1 ;用于测试在寄存器R1中是否设置了最低 位(%表示二进制数)
TST R1,#0xfe ;将寄存器R1的值与立即数0xfe按位 与,并根据结果设置CPSR的标志位
TEQ 指令
TEQ{条件} 操作数1,操作数2
- TEQ指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行
按位异或运算
,并根据运算结果更新CPSR中条件标志位的值。 - TEQ指令通常用于比较操作数1和操作数2
是否相等
算术指令
ADD 指令
ADD{条件}{S} 目的寄存器,操作数1,操作数2
- ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。
- 操作数1应是一个寄存器,
操作数2可以是一个寄存器,被移位的寄存器,或一个立即数
。 - 指令示例
ADD R0,R1,R2 ; R0 = R1 + R2
ADD R0,R1,#256 ; R0 = R1 + 256
ADDS R0,R2,R3,LSL#1 ; R0 = R2 + (R3 << 1)
ADC 指令
ADC{条件}{S} 目的寄存器,操作数1,操作数2
- ADC指令用于把两个操作数相加,
再加上CPSR中的C条件标志位的值
,并将结果存放到目的寄存器中。 - 它使用一个进位标志位,这样就可以
做比32位大的数的加法,注意不要忘记设置S后缀来更改进位标志。
ADC指令和ADD指令联合使用可以实现64位、128位的加法操作
- 以下指令序列
完成两个128位数的加法
,第一个数由高到低存放在寄存器R7~R4,第二个数由高到低存放在寄存器R11~R8,运算结果由高到低存放在寄存器R3~R0
ADDS R0,R4,R8 ; 加低端的字
ADCS R1,R5,R9 ; 加第二个字,带进位
ADCS R2,R6,R10 ; 加第三个字,带进位
ADC R3,R7,R11 ; 加第四个字,带进位
SUB 指令
SUB{条件}{S} 目的寄存器,操作数1,操作数2
- SUB指令用于把操作数1减去操作数2,并将结果存放到目的寄存器中。
- 该指令可用于有符号数或无符号数的减法运算。
- 指令示例
SUB R0,R1,R2 ; R0 = R1 - R2
SUB R0,R1,#256 ; R0 = R1 - 256
SUBS R0,R2,R3,LSL#1 ; R0 = R2 - (R3 << 1)
SBC 指令
SBC{条件}{S} 目的寄存器,操作数1,操作数2
- SBC指令用于把操作数1减去操作数2,再减去
CPSR中的C条件标志位的反码
,并将结果存放到目的寄存器中。 - 该指令使用进位标志来
表示借位
,这样就可以做大于32位的减法,注意不要忘记设置S后缀来更改进位标志。 - SBC指令和SUB指令联合使用可以实现64位、128位的减法操作
- 指令示例
SBC R0,R1,R2 ;R0 = R1 - R2 - !C,并根据结果设置CPSR的进位标志位
RSB 指令
RSB{条件}{S} 目的寄存器,操作数1,操作数2
- RSB指令称为
逆向减法指令
,用于把操作数2减去操作数1,并将结果存放到目的寄存器中。 - 该指令可用于有符号数或无符号数的减法运算。
- 指令示例
RSB R0,R1,R2 ; R0 = R2 – R1
RSB R0,R1,#256 ; R0 = 256 – R1
RSBS R0,R2,R3,LSL#1 ; R0 = (R3 << 1) - R2
RSC 指令
RSC{条件}{S} 目的寄存器,操作数1,操作数2
- RSC指令用于把操作数2减去操作数1,
再减去CPSR中的C条件标志位的反码
,并将结果存放到目的寄存器中。 - 该指令使用进位标志来表示借位,这样就可以做大于32位的减法,
注意不要忘记设置S后缀来更改进位标志。
- RSC指令和RSB指令联合使用可以实现64位、128位的减法操作
- 指令示例
RSC R0,R1,R2 ; R0 = R2 – R1 - !C
逻辑指令
AND 指令
AND{条件}{S} 目的寄存器,操作数1,操作数2
- AND指令用于在两个操作数上进行
逻辑与运算
,并把结果放置到目的寄存器中。 - 该指令常用于
屏蔽操作数1的某些位。
设置一个掩码值,AND指令可以提取寄存器中某些位的值
- 指令示例
AND R0,R0,#3 ; 该指令保持R0的0、1位,其余位 清零。
ORR 指令
ORR{条件}{S} 目的寄存器,操作数1,操作数2
- ORR指令用于在两个操作数上进行
逻辑或
运算,并把结果放置到目的寄存器中。 - 该指令常用于设置操作数1的某些位。
- 设置一个掩码值,ORR指令可以
设置寄存器中某些位的值为1
- 指令示例
ORR R0,R0,#3 ; 该指令设置R0的0、1位,其余位保持不变。
EOR 指令
EOR{条件}{S} 目的寄存器,操作数1,操作数2
- EOR指令用于在两个操作数上进行
逻辑异或运算
,并把结果放置到目的寄存器中。 - 该指令常用于反转操作数1的某些位。
- 设置一个掩码值,EOR指令可以将寄存器中某些位的值
取反
- 指令示例
EOR R0,R0,#3 ; 该指令反转R0的0、1位,其余位保持不变。
BIC 指令
BIC{条件}{S} 目的寄存器,操作数1,操作数2
- BIC指令用于
清除操作数1的某些位
,并把结果放置到目的寄存器中。 - 操作数2为32位的掩码,
如果在掩码中设置了某一位,则清除这一位,未设置的掩码位保持不变。
- 设置一个掩码值,BIC指令可以
将寄存器中某些位的值设置成0
- 指令示例
BIC R0,R0,#%1011 ; 该指令清除 R0 中的位 0、1、和3,其余的位保持不变。
乘法指令与乘加指令
- ARM微处理器支持的乘法指令与乘加指令共有6条,可
分为运算结果为32位和运算结果为64位
两类,与前面的数据处理指令不同指令中的所有操作数、目的寄存器必须为通用寄存器,不能对操作数使用立即数或被移位的寄存器
目的寄存器和操作数1必须是不同的寄存器。
- 乘法指令与乘加指令共有以下6条
- MUL 32位乘法指令
- MLA 32位乘加指令
- SMULL 64位有符号数乘法指令
- SMLAL 64位有符号数乘加指令
- UMULL 64位无符号数乘法指令
- UMLAL 64位无符号数乘加指令
MUL 指令
MUL{条件}{S} 目的寄存器,操作数1,操作数2
- MUL指令完成将操作数1与操作数2的乘法运算,并把结果放置到目的寄存器中,同时可以根据运算结果设置CPSR中相应的条件标志位。
- 其中,操作数1和操作数2
均为32位的有符号数或无符号数。
- 其中,操作数1和操作数2
结果仅保存了64位的低32位
- 指令示例
MUL R0,R1,R2 ;R0 = R1 × R2
MULS R0,R1,R2 ;R0 = R1 × R2,同时设置CPSR中的相关条件标志位
- 在早期的ARM版本中,
如果Rd和Rm是同一寄存器,则该行为是不可预测的。
(ARM Wiki和ARM官方文档)。
MLA 指令
MLA{条件}{S} 目的寄存器, 操作数1,操作数2,操作数3
- MLA指令完成将操作数1与操作数2的乘法运算,
再将乘积加上操作数3
,并把结果放置到目的寄存器中,同时可以根据运算结果设置CPSR中相应的条件标志位。 - 其中,操作数1和操作数2均为32位的
有符号数或无符号数。
- 指令示例
MLA R0,R1,R2,R3 ;R0 = R1 × R2 + R3
MLAS R0,R1,R2,R3 ;R0 = R1 × R2 + R3,同时设置CPSR中的相关条件标志位
SMULL 指令
SMULL{条件}{S} 目的寄存器Low,目的寄存器低High,操作数1,操作数2
- SMULL指令完成将操作数1与操作数2的乘法运算,
并把结果的低32位放置到目的寄存器Low中,结果的高32位放置到目的寄存器High中
,同时可以根据运算结果设置CPSR中相应的条件标志位。 - 其中,操作数1和操作数2均为32位的
有符号数。
- 指令示例
SMULL R0,R1,R2,R3
;R0 = (R2 × R3)的低32位
;R1 = (R2 × R3)的高32位
SMLAL 指令
SMLAL{条件}{S} 目的寄存器Low,目的寄存器低High,操作数1,操作数2
- SMLAL指令完成将操作数1与操作数2的乘法运算,
并把结果的低32位同目的寄存器Low中的值相加后又放置到目的寄存器Low中,结果的高32位同目的寄存器High中的值相加后又放置到目的寄存器High中
,同时可以根据运算结果设置CPSR中相应的条件标志位。 - 对于目的寄存器Low,在指令执行前存放64位加数的低32位,指令执行后存放结果的低32位。
- 对于目的寄存器High,在指令执行前存放64位加数的高32位,指令执行后存放结果的高32位。
- 其中,操作数1和操作数2均为32位的
有符号数。
- 指令示例
SMLAL R0,R1,R2,R3
;R0 = (R2 × R3)的低32位 + R0
;R1 = (R2 × R3)的高32位 + R1 + C
UMULL 指令
UMULL{条件}{S} 目的寄存器Low,目的寄存器低High,操作数1,操作数2
- UMULL指令完成操作同SMULL
- 其中,操作数1和操作数2均为
32位的无符号数。
UMLAL 指令
UMLAL{条件}{S} 目的寄存器Low,目的寄存器低 High,操作数1,操作数2
- UMLAL指令完成操作同SMLAL
- 其中,操作数1和操作数2均为
32位的无符号数。