文章目录
- Thumb指令集
- Coretx-M0汇编语言格式
- 寄存器访问指令:MOVE
- MOV Rd,#immed8.
- MOV Rd,Rm
- MOVS Rd,#immed8
- MOVS Rd,Rm
- MRS Rd,SpecialReg
- MSR SpecialReg,Rd
- 存储器访问指令:LOAD
- LDR Rt,[Rn,Rm]
- LDRH Rt,[Rn,Rm]
- LDRB Rt,[Rn,Rm]
- LDR Rt,[Rn,#immed5]
- LDRH Rt,[Rn,#immed5]
- LDR Rt,=立即数
- LDR Rt,[PC(SP),#immed8]
- LDRSH Rt,[Rn,Rm]
- LDRSB Rt,[Rn,Rm]
- 存储器访问指令:STORE
- STR Rt,[Rn,Rm]
- STRH Rt,[Rn,Rm]
- STRB Rt,[Rn,Rm]
- STR Rt,[Rn,#immed5]
- STRH Rt,[Rn,#immed5]
- STRB Rt,[Rn,#immed5]
- STR Rt,[SP, #immed8]
- 多数据访问指令:LDM和STM
- LDM Rn,{Ra,Rb,...}
- LDMIA Rn!,{Ra,Rb,...}
- STMIA Rn!,{Ra,Rb,...}
- 堆栈访问指令:PUSH和POP
- PUSH {Ra,Rb,...}
- POP {Ra,Rb,...}
- 算术运算指令
- 加法指令
- ADDS Rd,Rn,Rm
- ADDS Rd , Rn , #immed3
- ADDS Rd ,#immed8
- ADD Rd,Rm
- ADCS Rd,Rm
- ADD Rd,PC,#immed8
- ADR Rd,标号
- 减法指令
- SUBS Rd,Rn,Rm
- SUBS Rd,Rn,#immed3
- SUBS Rd,#immed8
- SBCS Rd,Rd,Rm
- RSBS Rd,Rm,#0
- 乘法指令
- MULS Rd,Rm,Rd
- 比较指令
- CMP Rn,Rm
- CMP Rn,#immed8
- CMN Rn,Rm
- 逻辑操作指令
- ANDS Rd,Rm
- ORRS Rd,Rm
- EORS Rd,Rm
- MVNS Rd,Rm
- BICS Rd,Rm
- TST Rd,Rm
- 移位操作指令
- 右移指令
- ASRS Rd,Rm
- ASRS Rd,Rm,#immed5
- LSRS Rd,Rm
- LSRS Rd,Rm,#immed5
- RORS Rd,Rm
- 左移指令
- LSLS Rd,Rm
- LSLS Rd,Rm,#immed5
- 反序操作指令
- REV Rd,Rm
- REV16 Rd,Rm
- REVSH Rd,Rm
- 扩展操作指令
- SXTB Rd,Rm
- SXTH Rd,Rm
- UXTB Rd,Rm
- UXTH Rd,Rm
- 程序流控制指令
- B label
- B cond label
- BL label
- BX Rm
- BLX Rm
- 存储器屏蔽指令
- DMB
- DSB
- ISB
- 异常相关指令
- SVC #immed8
- CPS
- 休眠相关指令
- WFl
- WFE
- SEV
- 其他指令
- NOP
- BKPT #immed8
- YIELD
- 参考资料:
Thumb指令集
在早期的 ARM 处理器中,使用了 32 位指令集,称为 ARM 指令。这个指集具有较高的运行性能。与8 位和 16 位的处理器相比,有更大的程序存储空间。但是,也带来较大的功耗。
在1995 年,16 位的 Thumb-1 指令集首先应用在ARM7TDMI 处理器上使用,它是 ARM指令集的子集。与 32 位的 RISC 结构相比,它提供更好的代码密度,将代码长度减少了 30%,但是性能也降低了20%。通过使用多路复用器,它能与 ARM 指令集一起使用。
Thumb-2 指令集由32位的Thumb 指令和最初的16位Thumb 指令组成与32位的ARM指令集相比,代码长度减少了 26%,但保持相似的运行性能。
Cortex-Mo采用了ARMv6-M 的结构,将电路规模降低到最小,它采用了16位Thumb-1的超集,以及 32位Thumb-2 的最小子集。下表给出了 Cortex-M0支持的 Thumb 指令以及Cortex-M0支持的32位Thumb 指令。
Coretx-M0汇编语言格式
ARM 汇编语言(适用于 ARM RealView 开发组件和 Keil)使用下面的指令格式:
标号
助记符 操作数 1 操作数 2,… ;注释
其中:
- 标号:用作地址位置的参考,即:符号地址。
- 助记符:指令的汇编符号表示。
- 操作数 1:目的操作数。
- 操作数2:源操作数。
- 注释:在符号“;”后表示是对该指令的注解。
对于不同类型的指令,操作数数量也会有所不同。有些指令不需要任何操作数,而有些指令只需要一个操作数。
例如:
对于下面的指令:
MOVS R3,#0x11 ;将立即数 0x11 复制到 R3 寄存器
可以通过ARM汇编器 (armasm) 或者不同厂商的汇编工具 (GNU工具链)对该代码进行汇编,将其转换成机器指令。当使用 GNU 工具链时,对标号和注释的语法会稍有不同。
对于 Cortex-M0的一些指令来说,需要在其后面添加后缀
后缀 | 标志 | 含义 |
---|---|---|
S | _ | 更新APSR(标志) |
EQ | Z=1 | 等于 |
NE | Z=0 | 不等于 |
CS/HS | C=1 | 高或者相同,无符号 |
CC/LO | C=0 | 低,无符号 |
MI | N=1 | 负数 |
PL | N=0 | 正数或零 |
VS | V=1 | 溢出 |
VC | V=0 | 无溢出 |
HI | C=1和Z=0 | 高,无符号 |
LS | C=0或Z=1 | 低或者相同,无符号 |
GE | N=V | 大于或者等于,有符号 |
LT | N!=V | 小于,有符号 |
GT | Z=0和N=V | 大于,有符号 |
LE | Z=1和N!=V | 小于等于,有符号 |
寄存器访问指令:MOVE
MOV Rd,#immed8.
该指令将立即数 immed8(8位,范围 0-255)复制到存器Rd中
例如:
MOV R0,#0x31
将寄存器R1的内容复制到寄存器R0中
MOV Rd,Rm
该指令将Rm寄存器的内容复制到Rd寄存器中
例如:
MOV R0,R1
将寄存器R1的内容复制到寄存器R0中。
MOVS Rd,#immed8
该指令将立即数immed8(8位,范围0~255)复制到寄存器 Rd 中,并且更新APSR寄存器中的Z和N 标志
例如:
MOVS R0,#0x31
将数字 0x31(十六进制)复制到寄存器R中(低8位),并且更新 APSR 寄存器中的Z和N标志。
MOVS Rd,Rm
该指令将Rm寄存器的内容复制到Rd寄存器中,并且更新APSR寄存器中的Z和N标志
例如:
MOVS R0,R1
将寄存器R1的内容复制到寄存器R0中,并且更新APSR寄存器中的标志。
MRS Rd,SpecialReg
该指令将由SpecialReg标识的特殊寄存器内容复制到寄存器Rd中,该指令不影响APSR寄存器中的任何标志位
例如:
MRS R1,CONTROL
将CONTROL寄存器的内容复制到寄存器R1中。
MSR SpecialReg,Rd
该指令将寄存器Rd中的内容复制到SpecialReg标识的特殊寄存器中,该指令影响 APSR寄存器中的N、Z、C和V标志
例如:
MSR PRIMASK,R0
将寄存器R0的内容复制到PRIMASK寄存器中。
SpecialReg所标识的特殊寄存器可以是以下任意一个:
APSR、IPSR、EPSR、IEPSR、IAPSR、EAPSR、PSR、MSP、PSP、PRIMASK、CONTROL。
存储器访问指令:LOAD
这些指令不影响APSR寄存器中的任何标志位。
LDR Rt,[Rn,Rm]
该指令从[Rn+Rm]寄存器所指向存储器的地址中,取出一个字(32 位),并将其复制到寄存器Rt中
例如:
LDR R0,[R1,R2]
该指令从[R1+R2]所指向存储器的地址中,取出一个字(32 位),并将其复制到寄存器R0中。
LDRH Rt,[Rn,Rm]
该指令从[Rn+Rm]寄存器所指向存储器的地址中,取出半个字(16 位),将其复制到寄存器Rt的[15:0]位中,并将寄存器Rt的[31:16]位清零
例如:
LDRH R0,[R1.R2]
该指令从[RI+R2]所指向存储器的地址中,取出半个字(16位),将其复制到存器R0的[15:0]位中。
LDRB Rt,[Rn,Rm]
该指令从[Rn+Rm]寄存器所指向存储器的地址中,取出一个字节(8 位),将其复制到寄存器Rt的[7:0]位中,并将寄存器Rt的[31:8]位清零,
例如:
LDRB R0,[R1,R2]
该指令从[R1+R2]寄存器所指向存储器中,取出一个字节(8 位),并将其复制到存器R0的[7:0]位中。
LDR Rt,[Rn,#immed5]
该指令从[Rn + 零扩展(=immed5<<2)]指向存储器的地址中,取出一个字(32 位),并将其复制到寄存器Rt的[31:0]位中。
例如:
LDR R0,[R1,#0x4]
该指令从[R1+0x4]所指向存储器的地址中,取出一个字 (32 位),并将其复制到寄存器R0中。
零扩展(#immed5<<2),表示给出立即数#immed5 的范图为0000000~1111111(即从0-127),并且满足字对齐关系,即:#immed5%4=0。
如下指令非法:
LDR R0,[R1,#80] ;立即数超过范围,80为128,超过127的范围
LDR R0,[R1,#7E] ;立即数7E没有字对齐#immed5为16进制数
LDRH Rt,[Rn,#immed5]
该指令从[Rn+零扩展(immed5<<1)]指向存储器的地址中,取出半个字(16 位),并将其复制到寄存器 Rt的[15:0]位中,用零填充[31:16]位。
例如:
LDRH R0,[R1,#0x2]
该指令从[R1+0x2]指向存储器的地址中,取出半个字(16 位),并将其复制到寄存器R0的[15:0]中,[31:16]用零填充。
零扩展 (#immed5<<1),表示给出立即数#immed5 的范图为 000000~111111(即从0-63),并且满足字对齐关系,即:#immed5%2=0。
如下指令非法:
LDR R0,[R1,#40] ;立即数超过范围,40为64,超过63的范围
LDR R0,[R1,#3E] ;立即数3E没有字对齐
LDR Rt,=立即数
该指令将立即数加载到寄存器 Rt 中。
例如:
LDR R0,=0x12345678
该指令将立即数0x12345678的值复制到寄存器R0中。
LDR Rt,[PC(SP),#immed8]
该指令从[PC(SP) +零扩展 (#immed8<<2)]指向存储器的地址中,取出一个字(32位),并将其复制到寄存器 Rt中。
例如:
LDR R0,[PC,#0x04]
该指令从[(PC)+0x04]指向存储器的地址中,取出一个字,并将其复制到寄存器R0中。
零扩展(#immed8<<2),表示给出立即数#immed8 的范围为0000000000~1111111111(即从0-1023),并且满足字对齐关系,即:#immed8%4=0。
LDRSH Rt,[Rn,Rm]
该指令从[Rn+Rm]所指向的存储器中取出半个字(16 位),并将其复制到Rt寄存器的[15:0]位中。对于[31:16]来说,取决于第[15]位,采用符号扩展。
- 当该位为1时,[31:16]各位均用1填充。
- 当该位为0时,[31:16]各位均用0填充。
例如:
LDRSH R0,[R1,R2]
该指令从[R1+R2]所指向的存储器地址中取出半个字 (16 位),并将其复制到R0寄存器的[15:0]位中,并进行符号扩展。
LDRSB Rt,[Rn,Rm]
从[Rn+Rm]所指向存储器的地址中取出一个字节 (8 位),并将其复制到 R 寄存器[7:0]中。对于[31:8]来说,取决于第[7]位,采用符号扩展。
- 当该位为1时,[31:8]各位均用1填充。
- 当该位为0时,[31:8]各位均用0填充。
例如:
LDRSB R0,[R1,R2]
该指令从[R1+R2]所指向的存储器中取出一个字节 (8 位),并将其复制到R0寄存器的[7:0]位中,并进行符号扩展。
存储器访问指令:STORE
这些指令不影响APSR寄存器中的任何标志位。
STR Rt,[Rn,Rm]
该指令将Rt寄存器中的字数据复制到[Rn+Rm]所指向存储器的地址单元中
例如:
STR R0,[R1,R2]
该指令将 R0 寄存器中的字数据复制到[R1+R2]所指向存储器地址单元中
STRH Rt,[Rn,Rm]
该指令将Rt寄存器的半字,即:[15:0]位复制到[Rn+Rm]所指向存储器的地址单元中
例如:
STRH R0,[R1,R2]
该指令将R0寄存器中的[15:0]位数据复制到[R1+R2]所指向存储器的地址单元中。
STRB Rt,[Rn,Rm]
该指令将Rt寄存器的字节,即:[7:0]位复制到[Rn+Rm]所指向存储器的地址单元中
例如:
STRB R0,[R1,R2]
该指令将R0寄存器中的[7:0]位复制到[R1+R2]所指向存储器的地址单元中。
STR Rt,[Rn,#immed5]
该指令将Rt寄存器的字数据复制到[Rn+零扩展 (#immed5<<2)]所指向存储器地址的单元中。
例如:
STR R0,[R1,#0x4]
将R0寄存器的字复制到[R1+0x04<<2]所指向存储器地址的单元中。
STRH Rt,[Rn,#immed5]
该指令将Rt寄存器的半字数据复制到[Rn+零扩展 (#immed5<<1)]所指向存储器地址的单元中。
例如:
STRH R0,[R1,#0x2]
将R0寄存器的半字复制到[R1+0x02]所指向存储器地址的单元中。
STRB Rt,[Rn,#immed5]
该指令将Rt寄存器的字节数据复制到[Rn+零扩展 (#immed5)]所指向存储器地址的单元中。
例如:
STRB R0,[R1,#0x1]
将R0寄存器的字节复制到[R1+0x01]所指向存储器地址的单元中。
STR Rt,[SP, #immed8]
该指令将Rt寄存器中的字数据复制到[SP+零扩展(#immed5<<2)]所指向存储器地址的单元中
STRB R0,[SP,#0x4]
该指令将将R0寄存器的字数据复制到[SP+(0x4)所指向存储器地址的单元中。
多数据访问指令:LDM和STM
LDM Rn,{Ra,Rb,…}
该指令将存储器的内容加载到多个寄存器中。
例如:
LDM R0,{R1,R2-R7}
-
将寄存器R0所指向存储器地址单元的内容复制到寄存器R1中。
-
将寄存器R0+4所指向存储器地址单元的内容复制到寄存器R2中。
-
将奇存器R0+8所指向存储器地址单元的内容复制到寄存器R3中。
…
-
将寄存器R0+24所指向存储器地址单元的内容复制到寄存器R7中。
LDMIA Rn!,{Ra,Rb,…}
该指令将存储器的内容加载到多个寄存器中,然后将Rn的值更新到最后一个地址+4的值。
例如:
LDMLA R0,{R1,R2-R7}
-
将寄存器R0所指向存储器地址单元的内容复制到寄存器R1中。
-
将寄存器R0+4所指向存储器地址单元的内容复制到寄存器R2中。
-
将寄存器R0+8所指向存储器地址单元的内容复制到寄存器R3中。
…
-
将寄存器R0+24所指向存储器地址单元的内容复制到寄存器R7中。
最后,将R0的值更新到最初R0+24+4的值。
! 表示更新寄存器 Rn 的值。
STMIA Rn!,{Ra,Rb,…}
该指令将多个寄存器的内容保存到存储器中,然后将Rn的值递增到最后一个地址+4的值。
例如:
STMIA R0!,{R1,R2-R7}
-
将寄存器R1的内容复制到寄存器R0所指向存储器地址的单元中。
-
将寄存器R2的内容复制到寄存器R0+4所指向存储器地址的单元中。
-
将寄存器R3的内容复制到寄存器R0+8所指向存储器地址的单元中。
…
-
将寄存器R7的内容复制到寄存器R0+24所指向存储器地址的单元中。
最后,将R0的值更新到最初R0+24+4的值。
! 表示更新寄存器 Rn 的值。
可用的寄存器范围为R0~R7。
对于STM来说,如果Rn也出现在列表中,则Rn应该是列表中的第一个寄存器。
堆栈访问指令:PUSH和POP
PUSH {Ra,Rb,…}
该指令将一个/多个寄存器保存到寄存器(入栈),并且更新堆栈指针寄存器
例如:
PUSH {R0,R1,R2}
- 将寄存器R0中的内容保存到SP-4所指向堆栈空间的地址单元中。
- 将寄存器R1中的内容保存到SP-8所指向堆栈空间的地址单元中。
- 将寄存器R2中的内容保存到SP-12所指向堆栈空间的地址单元中。
最后,将SP-12的结果作为SP最终的值
POP {Ra,Rb,…}
该指令将存储器中的内容恢复到多个寄存器中,并且更新堆栈指针寄存器
例如:
POP {R0,R1,R2}
- 将SP所指向堆栈空间地址单元的内容恢复到寄存器R2中。
- 将SP+4所指向堆栈空间地址单元的内容恢复到寄存器R1中。
- 将SP+8所指向堆栈空间地址单元的内容恢复到寄存器R0中。
最后,将SP+12的结果作为SP最终的值。
算术运算指令
算术运算指令包括加法指令、减法指令和乘法指令
加法指令
ADDS Rd,Rn,Rm
该指令将Rn寄存器的内容和Rm寄存器的内容相加,结果保存在寄存器Rd中,并且更新寄存器APSR中的N、Z、C和V标志
例如:
ADDS R0,R1,R2
该指令将R1寄存器的内容和R2寄存器的内容相加,结果保存在寄存器R0中,并且更新寄存器APSR中的标志。
ADDS Rd , Rn , #immed3
该指令将Rn寄存器的内容和立即数#immed3(该立即数的范围为000~111之间)相加,结果保存在寄存器Rd中,并且更新寄存器APSR中的 N、Z、C 和V标志
例如:
ADDS R0,R1,#0x01
该指令将R1寄存器的内容和立即数0x01相加,结果保存在寄存器R0中,并且更新寄存器APSR中的标志。
ADDS Rd ,#immed8
该指令将Rd寄存器的内容和立即数#immed8(该立即数的范围为 00000000~11111111之间)相加,结果保存在寄存器Rd中,并更新寄存器APSR中的N、Z、C和V标志
例如:
ADDS R0,#0x01
该指令将R0寄存器的内容和立即数0x01相加,结果保存在寄存器R0中,并且更新寄存器APSR中的标志。
ADD Rd,Rm
该指令将Rd寄存器的内容和Rm寄存器的内容相加,结果保存在寄存器Rd中,不更新寄存器APSR中的标志
例如:
ADD R0,R1
该指令将R0寄存器的内容和R1寄存器的内容相加,结果保存在寄存器R0中,不更新寄存器APSR中的标志。
ADCS Rd,Rm
该指令将Rd寄存器的内容、Rm寄存器的内容和进位标志相加,结果保存在寄存器Rd中,并且更新寄存器APSR 中的N、Z、C和V标志。
例如:
ADCS R0,R1
该寄存器将R0寄存器的内容、R1寄存器的内容和进位标志相加,结果保存在寄存器R0中并且更新寄存器APSR中的标志。
ADD Rd,PC,#immed8
该指令将PC寄存器的内容和立即数immed8相加,结果保存在寄存器Rd中,不更新奇存器APSR中的标志。
例如:
ADD R0,PC,#0x04
该指令将PC寄存器的内容和立即数0x04相加,结果保存在寄存器R0中,不更新存器APSR中的标志。
该立即数#immed8的范国为0x00000000~0x000003FF(0-1023)之间,且#immed8%4=0。
ADR Rd,标号
该指令将PC寄存器的内容与标号所表示的偏移量进行相加,结果保存在寄存器Rd中,不更新APSR中的标志。
例如:
ADR R3,JumpTable
该指令将 JumpTable 的地址加载到寄存器R3中。
标号必须是字对齐,且范围在0~1020个字节内,可以在汇编语言中使用ALIGN命令实现标号的字对齐。
减法指令
SUBS Rd,Rn,Rm
该指令将寄存器Rn的内容减去寄存器Rm的内容,结果保存在Rd中,并且更新寄存器APSR寄存器中的N、Z、C和V 标志
例如:
SUBS R0,R1,R2
该指令将寄存器R1的内容减去寄存器R2的内容结果保存在R0中,并且更新寄存器APSR寄存器中的标志。
SUBS Rd,Rn,#immed3
该指令将 Rn 寄存器的内容和立即数#immed3(该立即数的范围为 000~111之间)相减结果保存在寄存器 Rd 中,并且更新寄存器 APSR 中的 N、Z、C 和V标志
例如:
SUBS R0,R1,#0x01
该指令将 R1 寄存器的内容和立即数 0x01 相减,结果保存在寄存器 R0 中,并且更新寄存器APSR中的标志。
SUBS Rd,#immed8
该指令将 Rd 寄存器的内容和立即数#immed8(该立即数的范围为 00000000~11111111之间)相减,结果保存在寄存器 Rd 中,并更新存器APSR 中的N、Z、C和V标志
例如:
SUBS R0,#0x01
该指令将 R0 寄存器的内容和立即数0x01相减,结果保存在寄存器R0中,并且更新寄存器APSR中的标志。
SBCS Rd,Rd,Rm
该指令将 Rd 寄存器的内容、Rm 寄存器的内容和借位标志相减,结果保存在寄存器 Rd中,并且更新寄存器 APSR 中的N、Z、C和V标志。
例如:
SBCS R0,R0,R1
该寄存器将R0寄存器的内容R1寄存器的内容和借位标志相减,结果保存在寄存器R0中,并且更新寄存器 APSR 中的标志。
RSBS Rd,Rm,#0
该指令用数字0减去寄存器 Rm 中的内容,结果保存在寄存器 Rd 中,并且更新寄存器APSR 中的N、Z、C和V标志
例如:
RSBS R0,R0,#0
该指令用数字0减去寄存器R0中的内容,结果保存在寄存器R0中,并且更新寄存器 APSR中的标志。
乘法指令
MULS Rd,Rm,Rd
该寄存器将寄存器 Rm 的内容和寄存器 Rd 的内容相乘,结果保存在 Rd 寄存器中,并且更新寄存器 APSR 中的 N、Z、C和V标志
例如:
MULS R0,R1,R0
该寄存器将寄存器R1的内容和寄存器R0的内容相乘,结果保存在R0寄存器中,并且更新寄存器APSR中的标志。
比较指令
CMP Rn,Rm
该指令比较寄存器 Rn 和寄存器 Rm 的内容,得到(Rn) - (Rm)的结果,但不保存该结果,并且更新寄存器 APSR 中的 N、Z、C和V标志
例如:
CMP R0,R1
该指令比较寄存器 R0 和寄存器 R1 的内容,得到(R0) - (R1)的结果,但不保存该结果,并且更新寄存器APSR中的标志。
CMP Rn,#immed8
该指令将寄存器 Rn 的内容和立即数#immed8(其范围在0x00000000~0x000000FF之间)进行比较,得到(Rn)-#immed8 的结果,但不保存该结果,并且更新寄存器 APSR 中的 N、Z、C和V标志
例如:
CMP R0,#0x01
该指令将寄存器 R0 的内容和立即数#0x01进行比较,得到(R0) - 0x01 的结果,但不保存该结果,并且更新寄存器 APSR 中的标志。
CMN Rn,Rm
该指令比较寄存器 Rn 的内容和对寄存器 Rm 取反后内容,得到(Rn)+(Rm)的结果但不保存该结果,并且更新寄存器 APSR 中的 N、Z、C和V标志
例如:
CMN R0,R1
该指令比较寄存器 R0 和对寄存器 R1 取反后的内容,得到(R0)+(R1)的结果,但不保存该结果,并且更新寄存器 APSR 中的标志。
逻辑操作指令
ANDS Rd,Rm
该指令将寄存器 Rd 和寄存器 Rm 中的内容做“逻辑与”运算,结果保存在寄存器Rd中,并且更新寄存器APSR中的N和Z标志。
例如:
ANDS R0,R1
该指令将寄存器R0和寄存器R1中的内容做“逻辑与”运算,结果保存在寄存器R0中,并且更新寄存器APSR 中的标志。
ORRS Rd,Rm
该指令将寄存器 Rd 和存器 Rm 中的内容做“逻辑或”运算,结果保存在寄存器 Rd中,并且更新寄存器 APSR 中的 N 和Z标志
例如:
ORRS R0,R1
该指令将寄存器R0和寄存器R1中的内容做“逻辑或”运算,结果保存在寄存器R0中,并且更新寄存器APSR中的标志。
EORS Rd,Rm
该指令将寄存器 Rd 和寄存器 Rm 中的内容做“逻辑异或”运算,结果保存在寄存器 Rd中,并且更新寄存器 APSR 中的 N 和Z标志。
例如:
EORS R0,R1
该指令将寄存器 R0 和寄存器 R1 中的内容做“逻辑异或”运算,结果保存在寄存器 R0 中并且更新寄存器 APSR 中的标志。
MVNS Rd,Rm
该指令将奇存器 Rm 的[31:0]位按位做“逻辑取反”运算,结果保存在寄存器 Rd 中,并且更新寄存器 APSR 中的 N 和Z标志。
例如:
MVNS R0,R1
该指令将寄存器 R1的[31:]位按位做“逻辑取反”运算,结果保存在寄存器 R0 中,并且更新寄存器 APSR 中的标志。
BICS Rd,Rm
该指令将寄存器 Rm 的[31:0]位按位做“逻辑取反”运算,然后与寄存器 Rd 中的[31:0]位做“逻辑与”运算,结果保存在寄存器 Rd 中,并且更新寄存器 APSR 中的 N 和Z标志
例如:
BICS R0,R1
该指令将寄存器 R1的[31:0]位按位做“逻辑取反”运算,然后与寄存器 R0 中的[31:0]位做“逻辑与”操作,结果保存在奇存器 R0 中,并且更新寄存器 APSR 中的标志。
TST Rd,Rm
该指令将寄存器 Rd 和寄存器 Rm 中的内容做“逻辑与”运算,但是不保存结果,并且更新寄存器 APSR 中的 N和Z标志。
例如:
TST R0,R1
该指令将寄存器 R0 和寄存器 R1 中的内容做“逻辑与”运算,但是不保存结果,并且更新寄存器APSR中的标志。
移位操作指令
右移指令
ASRS Rd,Rm
该指令执行算术右移操作。将保存在寄存器 Rd 中的数据向右移动 Rm 所指定的次数移位的结果保存在寄存器 Rd 中,即: Rd=Rd>>Rm。在右移过程中,最后移出去的位保存在寄存器 APSR 的C标志中,也更新 N 和标志。
例如:
ASRS R0,R1
该指令将保存在寄存器 R0 中的数据向右移动 R1 所指定的次数,移位的结果保存在寄存器R0中。在右移过程中,最后移出去的位保存在寄存器 APSR 的C标志中,也更新N 和Z标志。
ASRS Rd,Rm,#immed5
该指令执行算术右移操作。将保存在寄存器 Rm 中的数据向右移动立即数#immed5 所指定的次数(范围在 1~32之间),移位的结果保存在寄存器 Rd 中,即: Rd=Rm>>#immed5。在右移过程中,最后移出去的位保存在寄存器 APSR的C 标志中,也更新 N 和Z标志。
例如:
ASRS R0,R1,#0x01
该指令将保存在寄存器 R1 中的数据向右移动 1 次,移位的结果保存在寄存器 R0 中在右移过程中,最后移出去的位保存在寄存器 APSR 的C标志中,也更新N 和Z标志。
LSRS Rd,Rm
该指令执行逻辑右移操作。将保存在寄存器 Rd 中的数据向右移动 Rm 所指定的次数移位的结果保存在寄存器 Rd 中,即: Rd=Rd>>Rm。在右移过程中,最后移出去的位保存在寄存器 APSR 的 C标志中,也更新 N 和Z标志。
例如:
LSRS R0, R1
该指令将保存在寄存器 R0 中的数据向右移动 R1 所指定的次数,移位的结果保存在寄存器R0中。在右移过程中,最后移出去的位保存在寄存器 APSR的C 标志中,也更新N 和Z标志。
LSRS Rd,Rm,#immed5
该指令执行逻辑右移操作。将保存在寄存器 Rm 中的数据向右移动立即数#immed5 所指定的次数(范围在 1~32之间),移位的结果保存在寄存器 Rd 中,即: Rd=Rm>>#immed5。在右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。
例如:
LSRS R0,R1,#0x01
该指令将保存在寄存器 R1 中的数据向右移动 1 次,移位的结果保存在寄存器 R0 中。在右移过程中,最后移出去的位保存在寄存器 APSR的C标志中,也更新N和Z标志。
RORS Rd,Rm
该指令执行循环右移操作。将保存在寄存器 Rd 中的数据向右循环移动 Rm 所指定的次数,移位的结果保存在寄存器 Rd中。在循环右移过程中,最后移出去的位保存在寄存器 APSR的C标志中,也更新N和Z标志
例如:
RORS R0,R1
该指令将保存在寄存器 R0 中的数据向右循环移动 R1 所指定的次数,移位的结果保存在寄存器 R0 中。在循环右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。
左移指令
LSLS Rd,Rm
该指令执行逻辑左移操作。将保存在寄存器 Rd 中的数据向左移动 Rm 所指定的次数移位的结果保存在寄存器 Rd 中,即:Rd=Rd<Rm。在左移过程中,最后移出去的位保存在寄存器 APSR 的Q标志中,也更新 N 和Z标志。
例如:
LSLS R0,R1
该指令将保存在寄存器 R0 中的数据向左移动 R1 所指定的次数,移位的结果保存在寄存器R0中。在左移过程中,最后移出去的位保存在寄存器 APSR 的 标志中,也更新 N 和Z标志
LSLS Rd,Rm,#immed5
该指令执行逻辑左移操作。将保存在寄存器 Rd 中的数据向左移动立即数#immed5 所指定的次数(范围在 1~32 之间),移位的结果保存在寄存器 Rd 中,即:Rd=Rm<<#immed5。在左移过程中,最后移出去的位保存在寄存器 APSR的C标志中,也更新N和Z标志。
例如:
LSLS R0,R1,#0x01
该指令将保存在寄存器R1中的数据向左移动1次,移位的结果保存在寄存器R0中。在左移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。
反序操作指令
REV Rd,Rm
该指令将寄存器 Rm 中字节的顺序按逆序重新排列,结果保存在寄存器Rd中
例如:
REV R0,R1
该指令将寄存器中R1的数据逆序重新排列**{R1[7:0],R1[15:8],R1[23:16],R1[31:24]}**,结果保存在寄存器R0中。
REV16 Rd,Rm
该指令将寄存器 Rm 中的内容以半字为边界,半字内的两个字节逆序重新排列,结果保存在奇存器 Rd中
例如:
REV16 R0,R1
该指令将寄存器中R1的数据以半字为边界,半字内的字节按逆序重新排列,即**{R1[23:16],R1[31:24],R1[7:0],R1[15:8]}**,结果保存在寄存器R0中。
REVSH Rd,Rm
该指令将寄存器Rm中的低半字内的两个字节逆序重新排列,结果保存在寄存器Rd[15:0中,对于Rd[31:16]中的内容由交换字节后R[7]的内容决定,即符号扩展
例如:
REVSH R0,R1
该指令将寄存器中 R1 的低半字内的两个字节按逆序重新排列,结果保存在寄存器 R0[15:0]中,对于R0[31:16]中的内容由交换字节后 R0[7]的内容决定,即符号扩展,表示为:
RO=符号扩展{R1[7:0],R1[15:8]}
扩展操作指令
SXTB Rd,Rm
将寄存器 Rm 中的[7:0]进行符号扩展,结果保存在寄存器 Rd 中。
例如:
SXTB R0,R1
该指令将寄存器 R1中的[7:0]进行符号扩展,结果保存在寄存器R0中,表示为:
R0=符号扩展{R1[7:0]}
SXTH Rd,Rm
将寄存器 Rm 中的[15:0]进行符号扩展,结果保存在寄存器 Rd 中。
例如:
SXTH R0,R1
该指令将寄存器 R1中的[15:0]进行符号扩展,结果保存在寄存器 R0 中,表示为:
RO=符号扩展{R1[15:0]}
UXTB Rd,Rm
将寄存器 Rm 中的[7:0]进行零扩展,结果保存在寄存器 Rd 中。
UXTB R0,R1
该指令将寄存器 R1 中的[7:0]进行零扩展,结果保存在寄存器 R0 中,表示为:
R0=零扩展{R1[7:0]}
UXTH Rd,Rm
将寄存器 Rm 中的[15:0]进行零扩展,结果保存在寄存器 Rd 中。
例如:
UXTH R0,R1
该指令将奇存器 R1中的[15:0]进行零扩展,结果保存在寄存器 R0 中,表示为:
R0=零扩展{R1[15:0]}
程序流控制指令
B label
该指令表示无条件跳转到label所标识的地址,跳转地址为当前PC 土 2046字节的范围内。
例如:
B loop
该指令实现无条件跳转到 loop 标识的地址。
B cond label
有条件跳转指令,根据寄存器 APSR 中的 N、Z、C和V 标志,跳转到 label 所标识的地址。
例如:
BEQ loop
当寄存器 APSR 寄存器中的标志位Z为1时(EQ后缀表示等于,即Z=1),将 PC 值修改为 loop 标号所表示的地址值,也就是跳转到标号为 loop 的位置执行程序
具体条件的表示参考上面后缀舍义。
BL label
该指令表示跳转和链接,跳转到一个地址,并且将返回地址保存到寄存器 LR 中。跳转地址为当前 PC 士 16M 字节的范围内。该指令通常用于调用一个子程序或者函数。一旦完成了函数,通过执行指令“BX LR”可以返回。
例如:
BL functionA
该指令将PC值修改为 functionA 标号所表示的地址值,寄存器 LR 的值等于PC+4
BX Rm
该指令表示跳转和交换,跳转到寄存器所指定的地址,根据寄存器的第0位的值(1 表示Thumb,0表示ARM),在 ARM 和 Thumb 模式之间切换处理器的状态
例如:
BX R0
该指令将 PC值修改为 R0 寄存器内的内容,即PC=R0
BLX Rm
跳转和带有交换的链接。跳转到寄存器所指定的地址,将返回地址保存到寄存器 LR 中,并且根据寄存器的第0位的值 (1表示 Thumb,0 表示ARM),在 ARM 和Thumb 模式之间切换处理器的状态。
例如:
BLX R0
该指令将 PC值修改为 R0 寄存器内的内容,即: PC=R0,并且寄存器 LR 的值等于 PC+4。
存储器屏蔽指令
DMB
数据存储器屏蔽指令。在提交新的存储器访问之前,确保已经完成所有的存储器访问。
DSB
数据同步屏蔽指令。在执行下一条指令前,确保已经完成所有的存储器访问。
ISB
指令同步屏蔽指令。在执行新的指令前,刷新流水线,确保已经完成先前所有的指令。
异常相关指令
SVC #immed8
管理员调用指令,触发 SVC 异常。
例如:
SVC #3
该指令表示触发SVC 异常,其参数为 3。
CPS
该指令修改处理器的状态,使能/禁止中断,该指令不会阻塞 NMI 和硬件故障句柄。
例如:
CPSIE 1 ;使能中断,清除 PRIMASK
CPSID 1 ;禁止中断,设置 PRIMASK
休眠相关指令
WFl
该指令等待中断,停止执行程序,直到中断到来或者处理器进入调试状态。
WFE
该指令等待事件,停止执行程序,直到事件到来(由内部事件寄存器设置)或者处理器进入调试状态。
SEV
在多处理环境 (包括自身) 中,向所有处理器发送事件。
其他指令
NOP
该指令为空操作指令,该指令用于产生指令对齐,或者引入延迟。
BKPT #immed8
该指令为断点指令,将处理器置位停止阶段。在该阶段,通过调试器,用户执行调试任务。由调试器插入 BKPT 指令,用于代替原来的指令。
immed8表示用于断点的标号,其范围为0x00~0xFF。
例如:
BKPT #0
该指令表示标号为0的断点。
YIELD
该指令用于表示停止一个任务。在多线程系统中,使用该指令用于表示延迟当前线程(比如等待硬件),并且能被交换/唤出。在 Cortex-M3 中,作为NOP 执行,即表示与 NOP 一样。
参考资料:
《ARM Cortex-M0 全可编程SoC原理及实现》