全网最详细的Cortex-M0指令集汇总

发布时间:2024年01月25日

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(标志)
EQZ=1等于
NEZ=0不等于
CS/HSC=1高或者相同,无符号
CC/LOC=0低,无符号
MIN=1负数
PLN=0正数或零
VSV=1溢出
VCV=0无溢出
HIC=1和Z=0高,无符号
LSC=0或Z=1低或者相同,无符号
GEN=V大于或者等于,有符号
LTN!=V小于,有符号
GTZ=0和N=V大于,有符号
LEZ=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}

  1. 将寄存器R0所指向存储器地址单元的内容复制到寄存器R1中。

  2. 将寄存器R0+4所指向存储器地址单元的内容复制到寄存器R2中。

  3. 将奇存器R0+8所指向存储器地址单元的内容复制到寄存器R3中。

  4. 将寄存器R0+24所指向存储器地址单元的内容复制到寄存器R7中。

LDMIA Rn!,{Ra,Rb,…}

该指令将存储器的内容加载到多个寄存器中,然后将Rn的值更新到最后一个地址+4的值。

例如:

LDMLA R0,{R1,R2-R7}

  1. 将寄存器R0所指向存储器地址单元的内容复制到寄存器R1中。

  2. 将寄存器R0+4所指向存储器地址单元的内容复制到寄存器R2中。

  3. 将寄存器R0+8所指向存储器地址单元的内容复制到寄存器R3中。

  4. 将寄存器R0+24所指向存储器地址单元的内容复制到寄存器R7中。

最后,将R0的值更新到最初R0+24+4的值。

! 表示更新寄存器 Rn 的值。

STMIA Rn!,{Ra,Rb,…}

该指令将多个寄存器的内容保存到存储器中,然后将Rn的值递增到最后一个地址+4的值。

例如:

STMIA R0!,{R1,R2-R7}

  1. 将寄存器R1的内容复制到寄存器R0所指向存储器地址的单元中。

  2. 将寄存器R2的内容复制到寄存器R0+4所指向存储器地址的单元中。

  3. 将寄存器R3的内容复制到寄存器R0+8所指向存储器地址的单元中。

  4. 将寄存器R7的内容复制到寄存器R0+24所指向存储器地址的单元中。

最后,将R0的值更新到最初R0+24+4的值。

! 表示更新寄存器 Rn 的值。

可用的寄存器范围为R0~R7。

对于STM来说,如果Rn也出现在列表中,则Rn应该是列表中的第一个寄存器。

堆栈访问指令:PUSH和POP

PUSH {Ra,Rb,…}

该指令将一个/多个寄存器保存到寄存器(入栈),并且更新堆栈指针寄存器

例如:

PUSH {R0,R1,R2}

  1. 将寄存器R0中的内容保存到SP-4所指向堆栈空间的地址单元中。
  2. 将寄存器R1中的内容保存到SP-8所指向堆栈空间的地址单元中。
  3. 将寄存器R2中的内容保存到SP-12所指向堆栈空间的地址单元中。

最后,将SP-12的结果作为SP最终的值

POP {Ra,Rb,…}

该指令将存储器中的内容恢复到多个寄存器中,并且更新堆栈指针寄存器

例如:

POP {R0,R1,R2}

  1. 将SP所指向堆栈空间地址单元的内容恢复到寄存器R2中。
  2. 将SP+4所指向堆栈空间地址单元的内容恢复到寄存器R1中。
  3. 将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原理及实现》

文章来源:https://blog.csdn.net/m0_73636161/article/details/135833268
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。