第5章CortexM0+处理器指令集



ARM架构是一种加载保存架构,具有32位寻址范围。ARM处理器是RISC处理器的典型代表,因为只有加载和保存指令才能访问存储器。数据处理指令仅对寄存器内容起作用。
本章介绍ARM CortexM0+处理器指令集,内容包括Thumb指令集、Keil MDK汇编语言指令格式要点、寄存器传输指令、存储器加载和保存指令、多数据加载和访问访问指令、堆栈访问指令、算术运算指令、逻辑操作指令、移位操作指令、反序操作指令、扩展操作指令、程序流控制指令、存储器屏障指令、异常相关指令、休眠相关指令和其他指令。
通过学习CortexM0+处理器指令集,使读者进一步了解和掌握CortexM0+处理器核的工作原理,从而更深刻地理解C语言、汇编语言和底层CortexM0+处理器核之间的联系。


视频讲解


5.1Thumb指令集
在早期的ARM处理器中,使用了32位指令集,称为ARM指令。这个指令集具有较高的运行性能,与8位和16位的处理器相比,有更大的程序存储空间。但是,这也带来了较大的功耗。
1995年,16位的Thumb1指令集首先应用于ARM7TDMI处理器,它是ARM指令集的子集。与32位的RISC结构相比,它提供更好的代码密度,将代码长度减少了30%,但是性能也降低了20%。通过使用多路复用器,它能与ARM指令集一起使用,如图5.1所示。


图5.1Thumb指令选择 


Thumb指令流是一系列采用半字对齐的半字。每条Thumb指令要么是该流中的单个16位半字,要么是包含该流中两个连续半字的32位指令。
如果要解码的半字的位域[15:11]取下面任何值,则该半字是32位指令的第一个半字: 
(1) 0b11101
(2) 0b11110
(3) 0b11111

否则,半字为16位指令。
Thumb2指令集由32位的Thumb指令和最初的16位Thumb指令组成,与32位的ARM指令集相比,代码长度减少了26%,但保持了相似的运行性能。
CortexM0+采用了ARMv6M的结构,将电路规模降低到最小,它采用了16位Thumb1的超集,以及32位Thumb2的最小子集。
CortexM0+支持的16位Thumb指令,如图5.2所示。


图5.2CortexM0+支持的16位Thumb指令


CortexM0+支持的32位Thumb指令,如图5.3所示。


图5.3CortexM0+支持的32位Thumb指令


思考与练习51: 请说明Thumb指令集的主要特点。
思考与练习52: 请说明Thumb1指令集和Thumb2指令集的区别。


视频讲解


5.2Keil MDK汇编语言指令格式要点
本节介绍在Keil μVision中编写汇编语言程序的一些最基本知识,帮助读者学习汇编语言助记符指令的书写规则。
5.2.1汇编语言源代码中的文字
汇编语言源代码可以包含数字、字符串、布尔值和单个字符文字。文字可以表示为: 
(1) 十进制数,例如123。 
(2) 十六进制数,例如0x7B。 
(3) 2~9的任何进制的数字。比如,5_204表示五进制数204,即
2×52+0×51+4×50=54

等效于十进制数的54。很明显,在采用五进制的数值表示中,有效的数字范围为0~4,这个规则适用于采用其他进制的数值表示,即在采用n进制的数值表示中,有效的数字范围为0~n-1。
(4) 浮点数,例如123.4。
(5) 布尔值{TRUE}或{FALSE}。
(6) 单引号引起来的单个字符值,例如'W'。
(7) 双引号引起来的字符串,例如"This is a string"。
注: 在大多数情况下,将包含单个字符的字符串看作单个字符值。例如,接受“ADD r0,r1,#"a"”,但是不接受“ADD r0,r1, #"ab"”。
此外还可以使用变量和名字来表示文字。
5.2.2汇编语言源代码行的语法
汇编器解析并对汇编语言进行汇编以生成目标代码。如图5.4所示,Keil MDK汇编语言源文件中的每一行代码都遵循下面的通用格式: 


{symbol} {instruction|directive|pseudo-instrunction} {;comment}



图5.4Keil MDK汇编语言源代码行的格式


其中: 
(1) {}表示可选部分,也就是说,每行代码的3个用符号{}括起来的部分都是可选的。
(2) symbol。通常是一个标号。在指令和伪指令中,它总是一个标号。在一些命令中,它是变量或常量的符号。
符号必须从第一列开始。除非用竖线(|)括起来,否则它不能包含空格或制表符之类的任何空格字符。
标号是地址的符号表示。可以使用标号来标记要从代码其他部分引用的特定地址。数字局部标签是标签的子类,标签的子类以0~99的数字开头。与其他标号不同,数字局部标号可以多次定义。这使得它们在使用宏生成标号时非常有用。
(3) instruction(指令)、directive(命令)、pseudoinstrunction(伪指令)。
① 命令用于指导汇编器和链接器对汇编语言程序的理解和处理,这些信息会影响汇编的过程或影响最终输出的镜像。命令并不能转换为机器指令(机器码)。
② 指令是指机器指令(机器码),在汇编语言程序设计中使用汇编语言助记符指令来描述机器指令。本质上,汇编语言程序代码主要是由汇编语言助记符指令构成的。通过使用汇编器和链接器对汇编语言助记符指令进行汇编和链接,转换为可以在CortexM0+处理器上执行的机器指令,以实现和完成特定的任务。如图5.5所示,使用汇编器对图5.4给出的汇编源代码进行汇编后,生成的机器指令序列。
注: 本章只详细介绍汇编语言助记符指令,而在第6章将详细介绍汇编语言助记符命令。
由图5.4和图5.5可知,一条汇编语言助记符指令由操作码和操作数构成。操作码说明指令要执行的操作类型,而操作数说明执行指令时,所需要操作对象的来源。操作数(操作对象)的来源可能是立即数、寄存器或存储器,这与每条指令的寻址方式有关。


图5.5对图5.4给出的汇编语言源代码进行汇编后的结果


(4) comment。注释是源代码行的最后一部分。每行上的第一个分号标记注释的开头,除非分号出现在字符串文字内。该行的结尾是注释的结尾。在代码行中,允许仅存在注释。在对汇编源代码进行汇编时,汇编器将忽略所有注释。可以加入空行使代码更具可读性。
注: (1) 在Keil μVision软件开发工具中,输入指令助记符、伪指令、命令和符号寄存器名字时,要么全部都使用大写字母,要么全部使用小写字母,不允许使用大小写混合的形式。标号和注释可以大写、小写或者大小写混合。
(2) 为了更容易阅读汇编源文件代码,可以通过在每行的默认放置反斜杠字符(\),将一行中很长的源代码分成几行。反斜杠后不能跟任何其他字符,包括空格和制表符。汇编器将反斜杠和后面跟随的行结束序列看作空白。此外,还可以加入空行使代码更具可读性。
5.2.3汇编语言指令后缀的含义
对于CortexM0+的一些汇编助记符指令来说,需要在其后面添加后缀,如表5.1所示。



表5.1后缀及含义


后缀标志含义

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小于或等于,有符号


5.3寄存器说明符的限制规则
本节介绍使用0b1111作为寄存器说明符和使用0b1101作为寄存器说明符的一些规则。
5.3.1使用0b1111作为寄存器说明符的规则
Thumb指令通常不允许将0b1111用作寄存器说明符。当允许寄存器的值为0b1111时,可能有多个含义。对于寄存器读,其含义为: 
(1) 读取PC的值,当前指令的地址加上4。某些指令不使用寄存器说明符而隐含读取PC值,例如条件分支指令 B<c>。
(2) 读取字对齐的PC值,即当前指令的地址+4,将[1:0]位强制设置为0。这使得ADR和LDR(literal)指令可以使用PC相对数据寻址。这些指令的ARMv6M编码中隐含了寄存器说明符。
对于寄存器写,其含义为: 
(1) 可以将PC指定为指令的目标寄存器。Thumb交互工作定义了是忽略地址的位[0]还是确定执行指令的状态。如果它在分支之后选择执行状态,则位[0]的值必须为1。
指令可以隐含写入PC,比如B<cond>,也可以使用寄存器掩码而不是寄存器说明符(POP)来编写。要跳转的地址可以是加载的值(例如POP)、寄存器的值(比如BX)或计算结果(例如ADD)。
(2) 丢弃计算结果。在某些情况下,当一条指令是另一条更通用指令的特殊情况,但丢弃结果时,可以执行该操作。在这些情况下,在单独的页面上列出指令,在伪代码中有特殊情况,用于更通用的指令交叉引用另一页面。该方法不适用于ARMv6M编码。
5.3.2使用0b1101作为寄存器说明符的规则
在Thumb指令集中定义了R13,它主要用作堆栈指针,使R13与ARM架构过程调用标准(ARM Architecture Procedure Call Standard,AAPCS)(PUSH和POP指令支持的架构使用模型)保持一致。
1. R13<1:0>的定义
R13的位[1:0]看作应为零或者保留(Should Be Zero or Preserved,SBZP),向位[1:0]写入非零的值会导致无法预料的行为。读取位[1:0]将返回零。
2. R13指令支持
ARMv6M中的R13指令支持仅限于以下各项: 
(1) R12作为MOV(寄存器)指令的源或目标寄存器,比如

MOV SP, Rm

MOV Rd, SP
(2) 通过对齐的倍数向上或向下调整R13,比如


SUB(SP减去立即数)

ADD(SP加上立即数)

ADD(SP加上寄存器)//Rm是4的倍数

(3) R13作为ADD(SP+寄存器)的第一个操作数<Rm>,其中Rd不是SP。
(4) R13作为CMP(寄存器)指令中的第一个操作数<Rn>。CMP对于检查堆栈非常有用。
(5) R13作为POP或PUSH指令中的地址。
限制影响: 
(1) 不推荐使用ADD(寄存器)和CMP(寄存器)的高寄存器形式,不建议使用R13作为Rd。
(2) ADD(SP+寄存器),其中Rd等于13,且Rm没有字对齐。


视频讲解


5.4寄存器传输指令
本节介绍写寄存器指令,下面对这些指令进行详细说明。
1. MOVS <Rd>, #imm8
该指令将立即数imm8(范围0~255)写到寄存器Rd中,该汇编助记符指令的机器码格式如图5.6所示。从该指令格式的机器码可知,Rd寄存器的使用范围为R0~R7。


图5.6MOVS <Rd>, #imm8指令的机器码格式


指令MOVS R1, #0x14的机器码表示为(2114)16。该指令将立即数0x14的内容写到寄存器R1中。并且更新APSR寄存器中的标志N、Z和C,但不修改标志V。
注: (2114)的下标16表示2114为十六进制数。

2. MOV <Rd>, <Rm>
该指令将寄存器Rm的内容写到寄存器Rd中,该汇编助记符指令的机器码格式如图5.7所示。从该指令的机器码格式可知,Rm可用的寄存器范围为R0~R15,Rd可用的寄存器范围为R0~R7。当Rd和D一起使用时,即{D,Rd},可用寄存器范围扩展到R0~R15。


图5.7MOV <Rd>, <Rm>指令的机器码格式


指令“MOV R0, SP”的机器码为(4668)16,将SP的内容写到寄存器R0中,不更新APSR寄存器中的标志。
3. MOVS <Rd>, <Rm>
该指令将寄存器Rm的内容复制到寄存器中Rd,并且更新APSR寄存器中的Z和N标志,该汇编助记符指令的机器码格式如图5.8所示。从该指令的机器码可知,Rm可用的寄存器范围为R0~R7,Rd可用的寄存器范围为R0~R7。


图5.8MOVS <Rd>,<Rm>指令的机器码格式


指令“MOVS R0, R1”的机器码为(0008)16。该指令将寄存器R1的内容复制到寄存器R0中,并且更新APSR寄存器中的标志N和Z。
4. MRS <Rd>, <SpecialReg>
该指令是32位的Thumb指令,将由SpecialReg标识的特殊寄存器(如表5.2所示)内容写到寄存器Rd中。该指令不影响APSR寄存器中的任何标志位,该汇编助记符指令的机器码格式如图5.9所示。从该指令的机器码格式可知,可用的Rd寄存器的范围为R0~R15。


图5.9MRS <Rd>, <SpecialReg>指令的机器码格式


SYSm的定义如表5.2所示。


表5.2SYSm的定义


SYSm的编码76543210


IPSR
EPSR
APSR
PSR
IEPSR
IAPSR
EAPSR
0
0
0
0
0
101
110
000
011
111
001
010


MSP
PSP
00001

000
001


PRIMASK
CONTROL
0
0
0
1
0
0
0
0
100

指令“MRS R1, CONTROL”的机器码为(F3EF8514)16。该指令将CONTROL寄存器的内容写到寄存器R1中。
5. MSR <SpecialReg>, <Rn>
该指令将寄存器Rn中的内容写到SpecialReg标识的特殊寄存器中,该指令影响APSR寄存器中的N、Z、C和V标志。该汇编助记符指令的机器码格式如图5.10所示。从该指令的机器码格式可知,可用的Rn寄存器的范围为R0~R15。SYSm的编码格式如表5.2所示。


图5.10MSR<SpecialReg>,<Rn>指令的机器码格式


指令“MSR APSR, R0”的机器码为(F3808800)16,将寄存器R0的内容写到APSR寄存器中。
思考与练习53: 说明下面指令所实现的功能。
(1) MOVS R0,#0x000B
(2) MOVS R1,#0x0
(3) MOV R10,R12
(4) MOVS R3,#23
(5) MOV R8,SP



视频讲解


5.5存储器加载和保存指令
本节介绍存储器加载和保存指令。
5.5.1存储器加载指令
下面对存储器加载指令进行详细说明。这些指令不会影响APSR寄存器中的任何标志位。
1. LDR <Rt>, [<Rn>,<Rm>]
该指令从[<Rn>+<Rm>]寄存器所指向存储器的地址中,取出一个字(32位),并将其写到寄存器Rt中,该汇编助记符指令的机器码格式如图5.11所示。可以看出,Rm、Rn和Rt所使用寄存器的范围为R0~R7。


图5.11LDR <Rt>, [<Rn>,<Rm>]指令的机器码格式


指令LDR R0, [R1, R2]的机器码为(5888)16。该指令从[R1+R2]所指向存储器的地址中,取出一个字(32位),并将其写到寄存器R0中。
2. LDRH <Rt>, [<Rn>,<Rm>]
该指令从[<Rn>+<Rm>]寄存器所指向存储器的地址中,取出半个字(16位),将其写到寄存器Rt的[15:0]位中,并将寄存器Rt的[31:16]位清零,该汇编助记符指令的机器码格式如图5.12所示。可以看出,Rm、Rn和Rt所使用寄存器的范围为R0~R7。


图5.12LDRH <Rt>, [<Rn>,<Rm>]指令的机器码格式


指令LDRH R0, [R1, R2]的机器码为(5A88)16。该指令从[R1+R2]所指向存储器的地址中,取出半个字(16位),将其写到寄存器R0的[15:0]位中。
3. LDRB <Rt>, [<Rn>,<Rm>]
该指令从[<Rn>+<Rm>]寄存器所指向存储器的地址中,取出单字节(8位),将其写到寄存器Rt的[7:0]位中,并将寄存器Rt的[31:8]位清零,该汇编助记符指令的机器码格式如图5.13所示。可以看出,Rm、Rn和Rt所使用寄存器的范围为R0~R7。


图5.13LDRB <Rt>, [<Rn>,<Rm>]指令的机器码格式


指令LDRB R0, [R1, R2]的机器码为(5C88)16。该指令从[R1+R2]寄存器所指向存储器中,取出1字节(8位),并将其写到寄存器R0的[7:0]位中。
4. LDR <Rt>, [<Rn>,#imm]
该指令从[<Rn> +imm]指向存储器的地址中,取出一个字(32位),并将其写到寄存器Rt中,该汇编助记符指令的机器码格式如图5.14所示。可以看出, Rn和Rt所使用寄存器的范围为R0~R7。


图5.14LDR <Rt>, [<Rn>,#imm]指令的机器码格式


注: (1) 该汇编语言助记符指令中允许的立即数imm的范围为0~124(7位二进制数),并且该立即数是4的整数倍。只是在对该立即数imm进行机器指令编码时,将汇编语言助记符指令中给出的立即数imm右移两位,然后得到该汇编指令中立即数在机器码中的编码格式为imm5,即为5位立即数。
(2) 将汇编语言助记符指令中的立即数imm零扩展到32位(imm5<<2)。
指令LDR R0, [R1, #0x7C]的机器码为(6FC8)16,该指令从[R1+0x7C]所指向存储器的地址中,取出一个字(32位),并将其写到寄存器R0中。
注: 对于汇编指令中给出的立即数0x7C,在将其转换为机器码格式时,右移两位,变成0x1F,因此机器指令的格式为(6FC8)16。
指令LDR R0,[R1,#0x80]中的立即数0x80超过范围,因此该指令是错误的。指令LDR R0,[R1,#0x7E]中的立即数0x7E没有字对齐(不是4的整数倍),因此该指令也是错误的。
5. LDRH <Rt>, [<Rn>,#imm]
该指令从[<Rn> +imm]指向存储器的地址中,取出半个字(16位),并将其写到寄存器Rt的[15:0]位中,用零填充[31:16]位。该汇编助记符指令的机器码格式如图5.15所示。可以看出, Rn和Rt所使用寄存器的范围为R0~R7。


图5.15LDRH <Rt>, [<Rn>,#imm]指令的机器码格式


注: (1) 该汇编语言助记符指令中允许的立即数imm的范围为0~62(6位二进制数),并且该立即数是2的整数倍。只是在对该立即数imm进行机器指令编码时,将汇编语言助记符指令中给出的立即数imm右移1位,然后得到该汇编指令中立即数在机器码中的编码格式为imm5,即为5位立即数。
(2) 将该汇编语言助记符指令中的立即数imm零扩展到32位(imm5<<1)。
指令LDRH R0, [R1, #0x3E]的机器码为(8FC8)16,该指令从[(R1)+(0x3E)]指向存储器的地址中,取出半个字(16位),并将其写到寄存器R0的[15:0]中,[31:16]用零填充。
注: 对于汇编指令中给出的立即数0x3E,在将其转换为机器码格式时,右移一位,变成0x1F,因此机器指令的格式为(8FC8)16。
指令LDRH R0,[R1,#0x40]中的立即数0x40超过范围,因此该指令是错误的。指令LDRH R0,[R1,#0x3F]中的立即数0x3F没有半字对齐,因此该指令也是错误的。
6. LDRB <Rt>, [<Rn>,#imm] 
该指令从[<Rn> +imm]指向存储器的地址中,取出单字节(8位),并将其写到寄存器Rt的[7:0]位中,用零填充[31:8]位。该汇编助记符指令的机器码格式如图5.16所示。可以看出, Rn和Rt所使用寄存器的范围为R0~R7。


图5.16LDRB <Rt>, [<Rn>,#imm]指令的机器码格式


注: (1) 该汇编语言助记符指令中允许的立即数imm5的范围为0~31(5位二进制数)。
(2) 该汇编语言助记符指令中的立即数imm=零扩展的立即数imm5。
指令LDRB R0, [R1, #0x1F]的机器码为(7FC8)16,该指令从[(R1)+0x1F]指向存储器的地址中,取出单字节,并将其写到寄存器Rt的[7:0]中。
7. LDR <Rt>, =立即数
该指令将立即数加载到寄存器Rt中。实际上,在Keil μVision编译器对该指令进行编译处理时,会转换为LDR<Rt>,[pc, #imm]的形式。因此,没有该指令的机器码编码格式,该指令为伪指令。该指令的存在只是方便编程人员直接对存储器空间的绝对地址进行操作而已。
注: 该伪指令生成最有效的单个指令以加载任何32位数字。可以使用该伪指令生成超出MOV和MVN指令范围的常量。
指令LDR R0, =0x12345678将立即数0x12345678的值加载到寄存器R0中。
8. LDR <Rt>, [PC, #imm]
该指令从[PC+imm]指向存储器的地址中,取出一个字,并将其写到寄存器Rt中,该汇编助记符指令的机器码格式如图5.17所示。可以看出, Rt所使用寄存器的范围为R0~R7。


图5.17LDR <Rt>, [PC, #imm]指令的机器码格式


注: (1) 该汇编语言助记符指令中允许的立即数imm的范围为0~1020(10位二进制数),并且该立即数是4的整数倍。只是在对该立即数imm进行机器指令编码时,将汇编语言助记符指令中给出的立即数imm右移2位,然后得到该汇编指令中立即数在机器码中的编码格式为imm8,即为8位立即数。
(2) 该汇编语言助记符指令中的立即数imm=零扩展到32位(imm8<<2)。
指令LDR R7, [PC, #0x44]的机器码为(4F11)16,该指令从[(PC)+0x44]指向存储器的地址中,取出一个字,并将其写到寄存器R7中。
注: 对于汇编指令中给出的立即数0x44,在将其转换为机器码格式时,右移两位,变成0x11,因此机器指令的格式为(4F11)16。

9. LDR <Rt>, [SP, #imm]
该指令从[SP+imm]指向存储器的地址中,取出一个字,并将其写到寄存器Rt中,该汇编助记符指令的机器码格式如图5.18所示。可以看出, Rt所使用寄存器的范围为R0~R7。


图5.18LDR <Rt>,[SP,#imm]指令的机器码格式


注: (1) 该汇编语言助记符指令中允许的立即数imm的范围为0~1020(10位二进制数),并且该立即数是4的整数倍。只是在对该立即数imm进行机器指令编码时,将汇编语言助记符指令中给出的立即数imm右移2位,然后得到该汇编指令中立即数在机器码中的编码格式为imm8,即为8位立即数。
(2) 该汇编语言助记符指令中的立即数imm=零扩展到32位(imm8<<2)。
指令LDR R0, [SP, #0x68]的机器码为(981A)16,该指令从[(SP)+0x68]指向存储器的地址中,取出一个字,并将其写到寄存器R0中。
注: 对于汇编指令中给出的立即数0x68,在将其转换为机器码格式时,右移两位,变成0x1A,因此机器指令的格式为(981A)16。
10. LDRSH <Rt>, [<Rn>,<Rm>]
该指令从[Rn+Rm]所指向的存储器中取出半个字(16位),并将其写到Rt寄存器的[15:0]位中。对于[31:16]来说,取决于第[15]位,采用符号扩展。当该位为1时,[31:16]各位均用1填充; 当该位为0时,[31:16]各位均用0填充,
该汇编助记符指令的机器码格式如图5.19所示。可以看出,Rm、Rn和Rt所使用寄存器的范围为R0~R7。


图5.19LDRSH <Rt>, [<Rn>,<Rm>]指令的机器码格式


指令LDRSH R0, [R1, R2]的机器码格式为(5E88)16。该指令从[R1+R2]所指向的存储器地址中取出半个字(16位),并将其写到R0寄存器的[15:0]位中,同时进行符号扩展。
11. LDRSB <Rt>, [<Rn>,<Rm>]
从[Rn+Rm]所指向存储器的地址中取出单字节(8位),并将其写到Rt寄存器[7:0]中。对于[31:8]来说,取决于第[7]位,采用符号扩展。当该位为1时,[31:8]各位均用1填充; 当该位为0时,[31:8]各位均用0填充,
该汇编助记符指令的机器码格式如图5.20所示。可以看出,Rm、Rn和Rt所使用寄存器的范围为R0~R7。


图5.20LDRSB <Rt>, [<Rn>,<Rm>]指令的机器码格式


指令LDRSB R0, [R1, R2]的机器码格式为(5688)16。该指令从[R1+R2]所指向的存储器中取出单字节(8位),并将其写到R0寄存器的[7:0]位中,同时进行符号扩展。
思考与练习54: 说明下面指令所实现的功能。
(1) LDR R1, =0x54000000
(2) LDRSH R1, [R2, R3]
(3) LDR R0, LookUpTable
(4) LDR R3, [PC, #100]
5.5.2存储器保存指令
本节介绍存储器保存指令,下面对这些指令进行详细说明。这些指令不影响APSR寄存器中的任何标志位。
1. STR <Rt>, [<Rn>,<Rm>]
该指令将Rt寄存器中的字数据写到 [<Rn>+<Rm>]所指向存储器的地址单元中,该汇编助记符指令的机器码格式如图5.21所示。可以看出,Rm、Rn和Rt所使用寄存器的范围为R0~R7。


图5.21STR <Rt>, [<Rn>,<Rm>]指令的机器码格式


指令STR R0, [R1, R2]的机器码格式为(5088)16。该指令将R0寄存器中的字数据写到 [R1+R2]所指向存储器地址单元中。
2. STRH <Rt>, [<Rn>,<Rm>]
该指令将Rt寄存器的半字,即[15:0]位写到 [<Rn>+<Rm>]所指向存储器的地址单元中,该汇编助记符指令的机器码格式如图5.22所示。可以看出,Rm、Rn和Rt所使用寄存器的范围为R0~R7。


图5.22STRH <Rt>, [<Rn>,<Rm>]指令的机器码格式


指令STRH R0, [R1, R2]的机器码格式为(5288)16。该指令将R0寄存器中的[15:0]位数据写到 [R1+R2]所指向存储器的地址单元中。
3. STRB <Rt>, [<Rn>,<Rm>]
该指令将Rt寄存器的字节,即: [7:0]位写到 [<Rn>+<Rm>]所指向存储器的地址单元中,该汇编助记符指令的机器码格式如图5.23所示。可以看出,Rm、Rn和Rt所使用寄存器的范围为R0~R7。


图5.23STRB <Rt>, [<Rn>,<Rm>]指令的机器码格式


指令STRB R0, [R1, R2]的机器码格式为(5488)16。该指令将R0寄存器中的[7:0]位写到 [R1+R2]所指向存储器的地址单元中。
4. STR <Rt>, [<Rn>,#imm]
该指令将Rt寄存器的字数据写到[<Rn> +imm]所指向存储器地址的单元中,该汇编助记符指令的机器码格式如图5.24所示。可以看出, Rn和Rt所使用寄存器的范围为R0~R7。


图5.24STR <Rt>, [<Rn>,#imm]指令的机器码格式


注: (1) 该汇编语言助记符指令中允许的立即数imm的范围为0~124(7位二进制数),并且该立即数是4的整数倍。只是在对该立即数imm进行机器指令编码时,将汇编语言助记符指令中给出的立即数imm右移2位(零扩展),然后得到该汇编指令中立即数在机器码中的编码格式为imm5,即为5位立即数。
(2) 该汇编语言助记符指令中的立即数imm=零扩展到32位(imm5<<2)。
指令STR R0, [R1, #0x44]的机器码格式为(6448)16,该指令将R0寄存器的字写到[R1+0x44]所指向存储器地址的单元中。
注: 对于汇编指令中给出的立即数0x44,在将其转换为机器码格式时,右移两位,变成0x11,因此机器指令的格式为(6448)16。
5. STRH <Rt>, [<Rn>, #imm] 
该指令将Rt寄存器的半字数据,即[15:0]位写到[<Rn> +imm]所指向存储器地址的单元中。该汇编助记符指令的机器码格式如图5.25所示。可以看出, Rn和Rt所使用寄存器的范围为R0~R7。


图5.25STRH <Rt>, [<Rn>, #imm]指令的机器码格式


注: (1) 该汇编语言助记符指令中允许的立即数imm的范围为0~62(6位二进制数),并且该立即数是2的整数倍。只是在对该立即数imm进行机器指令编码时,将汇编语言助记符指令中给出的立即数imm右移1位(零扩展),然后得到该汇编指令中立即数在机器码中的编码格式为imm5,即为5位立即数。
(2) 将该汇编语言助记符指令中的立即数imm=零扩展到32位(imm5<<1)。
指令STRH R0, [R1, #0x2]的机器码格式为(8048)16。该指令将R0寄存器的半字,即[15:0]位写到[R1+0x2]所指向存储器地址的单元中。
注: 对于汇编指令中给出的立即数0x2,在将其转换为机器码格式时,右移一位,变成0x1,因此机器指令的格式为(8048)16。
6. STRB <Rt>, [<Rn>,#imm]
该指令将Rt寄存器的字节数据写到[<Rn>+imm]所指向存储器的单元中。该汇编助记符指令的机器码格式如图5.26所示。可以看出, Rn和Rt所使用寄存器的范围为R0~R7。


图5.26STRB <Rt>, [<Rn>,#imm]指令的机器码格式


注: (1) 该汇编语言助记符指令中允许的立即数imm的范围为0~31(5位二进制数)。
(2) 该汇编语言助记符指令中的立即数imm=零扩展到32位(imm5)。
指令STRB R0, [R1, #0x1]的机器码格式为(7048)16。该指令将R0寄存器的字节[7:0]位写到[R1+0x01]所指向存储器地址的单元中。
7. STR <Rt>, [SP, #imm] 
该指令将Rt寄存器中的字数据写到[SP+imm]所指向存储器地址的单元中。该汇编助记符指令的机器码格式如图5.27所示。可以看出,Rt所使用寄存器的范围为R0~R7。


图5.27STR <Rt>, [SP, #imm]指令的机器码格式


注: (1) 该汇编语言助记符指令中允许的立即数imm的范围为0~1020(10位二进制数),并且该立即数是4的整数倍。只是在对该立即数imm进行机器指令编码时,将汇编语言助记符指令中给出的立即数imm右移2位(零扩展),然后得到该汇编指令中立即数在机器码中的编码格式为imm8,即为8位立即数。
(2) 该汇编语言助记符指令中的立即数imm=零扩展到32位(imm8<<2)。
指令STR R0, [SP, #0x8]的机器码格式为(9002)16。该指令将将R0寄存器的字数据写到[SP+(0x8)]所指向存储器地址的单元中。
注: 对于汇编指令中给出的立即数0x8,在将其转换为机器码格式时,右移两位,变成0x2,因此机器指令的格式为(9002)16。
思考与练习55: 说明下面指令所实现的功能。
(1) STR R0, [R5, R1]
(2) STR R2, [R0,#conststruc]


视频讲解


5.6多数据加载和保存指令
本节介绍多数据加载和保存指令。
5.6.1多数据加载指令
本节介绍多数据加载指令,包括LDM、LDMIA和LDMFD。它们使用基址寄存器中的地址从连续的存储器位置中加载多个寄存器后,加载多个增量。连续的存储器位置从该地址开始,并且当基址寄存器Rn不属于<registers>列表时,这些位置的最后一个地址之上的地址将写回到基址寄存器。
下面对LDM指令进行详细说明,该指令有两种形式,包括: 

LDM <Rn>!,<registers>
<registers>中不包含<Rn>

LDM <Rn>,<registers>
<registers>中包含<Rn>

注: (1) !的作用是: 使指令将修改后的值写回到<Rn>。如果没有!,则指令不会以这种方式修改<Rn>。
(2) registers是要加载的一个或多个寄存器的列表,用逗号分隔,并且用{}符号包围。编号最小的寄存器从最低的存储器地址加载,直到从最高存储器地址到编号最高的寄存器。
该汇编助记符指令的机器码格式如图5.28所示。可以看出,Rn所使用寄存器的范围为R0~R7。


图5.28LDM指令的机器码格式


注: 图中register_list字段中的每一个比特位对应一个寄存器。register_list[7]对应寄存器R7; register_list[6]对应寄存器R6; register_list[5]对应寄存器R5; register_list[4]对应寄存器R4; register_list[3]对应寄存器R3; register_list[2]对应寄存器R2; register_list[1]对应寄存器R1; register_list[0]对应寄存器R0。当<register>存在某个寄存器时,register_list字段中对应的位置为1,否则为0。
指令LDM R0!, {R1,R2-R7}的机器码格式为(C8FE)16 。该指令实现下面的功能: 
(1) 将寄存器R0所指向存储器地址单元的内容复制到寄存器R1中。
(2) 将寄存器R0+4所指向存储器地址单元的内容复制到寄存器R2中。
(3) 将寄存器R0+8所指向存储器地址单元的内容复制到寄存器R3中。
……
(7) 将寄存器R0+24所指向存储器地址单元的内容复制到寄存器R7中。
(8) 用R0+4×7的值更新寄存器R0的内容。
注: LDMIA和LDMFD为LDM指令的伪指令。LDMIA是LDM指令的别名,用法同LDM。LDMFD是同一指令的另一个名字,在使用软件管理堆栈的传统ARM系统中,该指令用于从全递减堆栈中还原数据。
5.6.2多数据保存指令
本节介绍多数据保存指令,包括STM、STMIA和STMEA。使用来自基址寄存器的地址将多个寄存器的内容保存到连续的存储器位置。随后的存储器位置从该地址开始,并且这些位置的最后一个地址之上的地址将写回到基址寄存器。指令格式如下:

STM <Rn>!, <registers>

注: (1) !的作用是: 使指令将修改后的值写回到<Rn>。
(2) registers是要加载的一个或多个寄存器的列表,用逗号分隔,并且用{}符号包围。编号最小的寄存器从最低的存储器地址加载,直到从最高存储器地址到编号最高的寄存器。不推荐在寄存器列表中使用<Rn>。
该汇编助记符指令的机器码格式如图5.29所示。


图5.29STM <Rn>!, <registers>指令的机器码格式


注: 图中register_list的具体含义同图5.28。
指令STM R0!, {R1, R2-R7}的机器码格式为(C0FE)16 。该指令实现下面的功能: 
(1) 将寄存器R1的内容复制到寄存器R0所指向存储器地址的单元中。
(2) 将寄存器R2的内容复制到寄存器R0+4所指向存储器地址的单元中。
(3) 将寄存器R3的内容复制到寄存器R0+8所指向存储器地址的单元中。
……
(7) 将寄存器R7的内容复制到寄存器R0+24所指向存储器地址的单元中。
(8) 用R0+7×4的值更新R0寄存器的值。
思考与练习56: 说明下面指令所实现的功能。
(1) LDM R0,{R0,R3,R4}
(2) STMIA R1!,{R2-R4,R6}


视频讲解


5.7堆栈访问指令
本节介绍堆栈访问指令,包括PUSH和POP,下面对这些指令进行详细说明。
1. PUSH <registers>
该指令将一个/多个寄存器(包括R0~R7以及LR)保存到堆栈(入栈),并且更新堆栈指针寄存器,该汇编助记符指令的机器码格式如图5.30所示。


图5.30PUSH <registers>指令的机器码格式


注: (1) registers是一个或多个寄存器的列表,用逗号分隔,并且用{}符号包围。它标识了将要保存的寄存器集,按顺序保存。编号最小的寄存器到最低的存储器地址,一直到编号最大的寄存器到最高的存储器地址。registers='0':M:'000000':register_list。
(2) 图中register_list的具体含义同图5.28。
指令PUSH{R0,R1,R2},该指令机器码的格式为(B407)16,该指令实现下面功能:
(1) (sp)=(sp)-4×进入堆栈的寄存器的个数。
(2) 将寄存器R0的内容保存到(sp)所指向的存储器的地址。
(3) 将寄存器R1的内容保存到(sp)+4所指向的存储器的地址。
(4) 将寄存器R2的内容保存到(sp)+8所指向的存储器的地址。
(5) 将sp的内容更新到步骤(1)计算得到的sp内容。
2. POP <registers>
该指令将存储器中的内容恢复到多个寄存器(包括R0~R7以及PC)中,并且更新堆栈指针寄存器的机器码格式如图5.31所示。


图5.31POP <registers>指令的机器码格式


注: (1) registers是一个或多个寄存器的列表,用逗号分隔,并且用{}符号包围。它标识了将要加载的寄存器集。从最低的存储器地址加载到编号最小的寄存器,从最高的存储器地址加载到编号最大的寄存器。如果在<registers>中指定了PC,则该指令将导致跳转到PC中加载的地址(数据)。
(2) 图中register_list的具体含义同图5.28。registers=P:'0000000':register_list。
指令POP{R0,R1,R2},该指令的机器码为(BC07)16,该指令实现下面的功能:
(1) 将(sp)所指向的存储器的内容加载到寄存器R0。
(2) 将(sp)+4所指向的存储器的内容加载到寄存器R1。
(3) 将(sp)+8所指向的存储器的内容加载到寄存器R2。
(4) 用(sp)+4×出栈寄存器的个数的值更新寄存器sp。
思考与练习57: 说明下面指令所实现的功能。
(1) PUSH{R0,R4-R7}
(2) PUSH{R2,LR}
(3) POP{R0,R6,PC}


视频讲解


5.8算术运算指令
本节介绍算术运算指令,包括加法指令、减法指令和乘法指令。
5.8.1加法指令
1. ADDS <Rd>, <Rn>, <Rm>

该指令将Rn寄存器的内容和 Rm寄存器的内容相加,结果保存在寄存器Rd中,同时更新寄存器APSR中的N、Z、C和V标志,该汇编助记符指令的机器码格式如图5.32所示。可以看出,寄存器Rm、Rn和Rd可用的范围为R0~R7。


图5.32ADDS <Rd>, <Rn>, <Rm>指令的机器码格式


指令ADDS R0, R1, R2的机器码为(1888)16。该指令将R1寄存器的内容和 R2寄存器的内容相加,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
2. ADDS <Rd>, <Rn>, #imm3
该指令将Rn寄存器的内容和立即数imm3相加,结果保存在寄存器Rd中,同时更新寄存器APSR中的N、Z、C和V标志,该汇编助记符指令的机器码格式如图5.33所示。可以看出,寄存器Rn和Rd可用的范围为R0~R7。


图5.33ADDS <Rd>, <Rn>, #imm3指令的机器码格式


注: 图中imm3的范围为0~7。
指令ADDS R0, R1, #0x07的机器码为(1DC8)16。该指令将R1寄存器的内容和立即数0x07相加,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
3. ADDS <Rd>, #imm8
该指令将Rd寄存器的内容和立即数imm8相加,结果保存在寄存器Rd中,同时更新寄存器APSR中的N、Z、C和V标志,该汇编助记符指令的机器码格式如图5.34所示。可以看出,寄存器Rd可用的范围为R0~R7。


图5.34ADDS <Rd>, #imm8指令的机器码格式


注: 图中imm8的范围为0~255。
指令ADDS R0, #0x01的机器码为(3001)16。该指令将R0寄存器的内容和立即数0x01相加,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
4. ADD <Rd>, <Rm>
该指令将Rd寄存器的内容和Rn寄存器的内容相加,结果保存在寄存器Rd中,不更新寄存器APSR中的标志,该汇编助记符指令的机器码格式如图5.35所示。可以看出,寄存器Rm可用的范围为R0~R15,DN与Rd组合后可用的范围为R0~R15。


图5.35ADD <Rd>, <Rm>指令的机器码格式


指令ADD R0, R1的机器码为(4408)16,该指令将R0寄存器的内容和 R1寄存器的内容相加,结果保存在寄存器R0中,不更新寄存器APSR中的标志。 
5. ADCS <Rd>, <Rm>
该指令将Rd寄存器的内容、Rm寄存器的内容和进位标志相加,结果保存在寄存器Rd中,同时更新寄存器APSR中的N、Z、C和V标志,该汇编助记符指令的机器码格式如图5.36所示。可以看出,寄存器Rm和Rd可用的范围为R0~R7。


图5.36ADCS <Rd>, <Rm>指令的机器码格式


指令ADCS R0, R1的机器码为(4148)16。该寄存器将R0寄存器的内容、R1寄存器的内容和进位标志相加,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。 
6. ADD <Rd>, PC, #imm
该指令将PC寄存器的内容和立即数#imm相加,结果保存在寄存器Rd中,不更新寄存器APSR中的标志。该汇编助记符指令格式的机器码与指令ADR <Rd>, <label>相同,如图5.37所示。


图5.37ADR <Rd>, <label>指令的机器码格式


注: (1) 在相加的时候,必须将PC寄存器的内容与字对齐,即Align(PC,4)。
(2) 该汇编语言助记符指令中允许的立即数imm的范围为0~1020(10位二进制数),并且该立即数是4的整数倍。只是在对该立即数imm进行机器指令编码时,将汇编语言助记符指令中给出的立即数imm右移2位(零扩展),然后得到该汇编指令中立即数在机器码中的编码格式为imm8,即为8位立即数。
(3) 该汇编语言助记符指令中的立即数imm=零扩展到32位(imm8<<2)。
指令ADD R0, PC, #0x04的机器码为(A001)16。该指令将PC寄存器的内容(字对齐)和立即数0x04相加,结果保存在寄存器R0中,不更新寄存器APSR中的标志。
7. ADR <Rd>,<label >
该指令将PC寄存器的内容与标号所表示的偏移量进行相加,结果保存在寄存器Rd中,不更新APSR中的标志。<label>为将地址加载到<Rd>中的指令或文字数据项的标号。汇编器计算从ADR指令的Align(PC,4)值到该标签的偏移量所需要的值。偏移量的允许值是0~1020范围内的正数(4的倍数)。
指令ADR R3, JumpTable将JumpTable的地址加载到寄存器R3中。
8. ADD(SP加立即数指令)
该类型指令有两个指令类型。

1) ADD <Rd>, SP, #imm
该指令实现将堆栈指针SP的内容和立即数imm相加,相加的结果写到寄存器Rd中。该汇编助记符指令的机器码格式如图5.38所示。可以看出,寄存器Rd可用的范围为R0~R7。


图5.38ADD <Rd>, SP, #imm8指令的机器码格式


注: (1) 图中imm8的含义同图5.37。
(2) 该指令中imm的范围为0~1020,且imm为4的整数倍。
指令ADD R3,SP,#0x04的机器码格式为(AB01)16,该指令实现将堆栈指针SP的内容和立即数0x04相加,相加的结果写到寄存器R3中。
2) ADD SP,SP,#imm
该指令实现将堆栈指针SP的内容和立即数imm相加,相加的结果写到堆栈指针中。该汇编助记符指令的机器码格式如图5.39所示。


图5.39ADD SP,SP,#<imm>指令的机器码格式


注: (1) 该汇编语言助记符指令中允许的立即数imm的范围为0~508(9位二进制数),并且该立即数是4的整数倍。只是在对该立即数imm进行机器指令编码时,将汇编语言助记符指令中给出的立即数imm右移2位(零扩展),然后得到该汇编指令中立即数在机器码中的编码格式为imm7,即为7位立即数。
(2) 该汇编语言助记符指令中的立即数imm=零扩展到32位(imm7<<2)。
指令ADD SP,SP,#08的机器码格式为(B002)16,该指令实现将堆栈指针SP的内容和立即数0x08相加,相加的结果写到堆栈指针SP中。
5.8.2减法指令
1. SUBS <Rd>, <Rn>, <Rm>

该指令将寄存器Rn的内容减去寄存器Rm的内容,结果保存在Rd中,同时更新寄存器APSR寄存器中的N、Z、C和V标志。该汇编助记符指令的机器码格式如图5.40所示。可以看出,寄存器Rm、Rn和Rd可用的范围为R0~R7。


图5.40SUBS <Rd>, <Rn>, <Rm>指令的机器码格式


指令SUBS R0, R1, R2的机器码格式为(1A88)16。该指令将寄存器R1的内容减去寄存器R2的内容,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
2. SUBS <Rd>, <Rn>, #imm3
该指令将Rn寄存器的内容和立即数imm3相减,结果保存在寄存器Rd中,同时更新寄存器APSR中的N、Z、C和V标志。该汇编助记符指令的机器码格式如图5.41所示。可以看出,寄存器Rn和Rd可用的范围为R0~R7。


图5.41SUBS <Rd>, <Rn>, #imm3指令的机器码格式


注: imm3的范围为0~7。
指令SUBS R0, R1, #0x01的机器码为(1E48)16。该指令将R1寄存器的内容和立即数0x01相减,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
3. SUBS <Rd>, #imm8
该指令将Rd寄存器的内容和立即数#imm8相减,结果保存在寄存器Rd中,同时更新寄存器APSR中的N、Z、C和V标志。该汇编助记符指令的机器码格式如图5.42所示。可以看出,寄存器Rd可用的范围为R0~R7。


图5.42SUBS <Rd>, #imm8指令的机器码格式


注: imm8的范围为0~255。
指令SUBS R0, #0x01的机器码为(3801)16。该指令将R0寄存器的内容和立即数0x01相减,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
4. SBCS <Rd>, <Rm>
该指令将Rd寄存器的内容、Rm寄存器的内容和借位标志相减,结果保存在寄存器Rd中,同时更新寄存器APSR中的N、Z、C和V标志。该汇编助记符指令的机器码格式如图5.43所示。可以看出,寄存器Rd和Rm可用的范围为R0~R7。


图5.43SBCS <Rd>, <Rm>指令的机器码格式


指令SBCS R0, R0, R1的机器码为(4188)16。该寄存器将R0寄存器的内容、R1寄存器的内容和借位标志相减,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。 
5. RSBS <Rd>, <Rn>, #0
该指令用数字0减去寄存器Rn中的内容,结果保存在寄存器Rd中,并且更新寄存器APSR中的N、Z、C和V标志。该汇编助记符指令的机器码格式如图5.44所示。可以看出,寄存器Rd和Rn可用的范围为R0~R7。


图5.44RSBS <Rd>, <Rm>, #0指令的机器码格式


指令RSBS R0, R0, #0的机器码为(4240)16。该指令用数字0减去寄存器R0中的内容,结果保存在寄存器R0中,并且更新寄存器APSR中的标志。
6. SUB SP,SP,#imm
该指令将堆栈指针SP的内容减去立即数imm,结果保存在堆栈指针SP中。该指令不影响APSR中的标志。该汇编助记符指令的机器码格式如图5.45所示。


图5.45SUB SP,SP,#imm指令的机器码格式


注: 图中imm7的含义同图5.39。
指令SUB SP,SP,#0x18的机器码格式为(B086)16,该指令实现将堆栈指针SP的内容和立即数0x18相减,相减的结果写到堆栈指针SP中。
5.8.3乘法指令
MULS <Rd>, <Rn>, <Rd>
该指令将寄存器Rn的内容和寄存器Rd的内容相乘,低32位结果保存在Rd寄存器中,同时更新寄存器APSR中的 N和Z标志,但不影响C和V标志。该汇编助记符指令的机器码格式如图5.46所示。可以看出,寄存器Rd和Rn可用的范围为R0~R7。


图5.46MULS <Rd>, <Rn>, <Rd>指令的机器码格式


指令MULS R0, R1, R0的机器码为(4348)16。该指令将寄存器R1的内容和寄存器R0的内容相乘,低32位结果保存在R0寄存器中,同时更新寄存器APSR中的标志。
5.8.4比较指令
1. CMP <Rn>, <Rm>

该指令比较寄存器Rn和寄存器Rm的内容,得到(Rn)―(Rm)的结果,但不保存该结果,同时更新寄存器APSR中的N、Z、C和V标志。该汇编助记符指令的机器码格式如图5.47所示。可以看出,寄存器Rn和Rm可用的范围为R0~R7。


图5.47CMP <Rn>, <Rm>指令的机器码格式


指令CMP R0, R1的机器码为(4288)16。该指令比较寄存器R0和寄存器R1的内容,得到(R0)―(R1)的结果,但不保存该结果,同时更新寄存器APSR中的标志。
2. CMP <Rn>, #imm8
该指令将寄存器Rn的内容和立即数#imm8(零扩展到32位)进行比较,得到(Rn)―imm8的结果,但不保存该结果,同时更新寄存器APSR中的N、Z、C和V标志。该汇编助记符指令的机器码格式如图5.48所示。可以看出,寄存器Rn可用的范围为R0~R7。


图5.48CMP <Rn>, #imm8指令的机器码格式


注: 图中立即数imm8的范围为0~255(其零扩展到32位)。
指令CMP R0, #0x01的机器码为(2801)16。该指令将寄存器R0的内容和立即数0x01进行比较,得到(R0)―0x01的结果,但不保存该结果,同时更新寄存器APSR中的标志。
3. CMN <Rn>, <Rm>
该指令比较寄存器Rn的内容和对寄存器Rm取反后内容,得到(Rn)+(Rm)的结果,但不保存该结果,同时更新寄存器APSR中的N、Z、C和V标志。该汇编助记符指令的机器码格式如图5.49所示。可以看出,寄存器Rn和Rm可用的范围为R0~R7。


图5.49CMN <Rn>, <Rm>指令的机器码格式


指令CMN R0, R1的机器码为(42C8)16。该指令比较寄存器R0和对寄存器R1取反后的内容,得到(R0)+(R1)的结果,但不保存该结果,同时更新寄存器APSR中的标志。
思考与练习58: 将保存在寄存器R0和R1内的64位整数,与保存在寄存器R2和R3内的64位整数相加,结果保存在寄存器R0和R1中。使用ADDS和ADCS指令实现该64位整数相加功能。
思考与练习59: 将保存在寄存器R1、R2和R3内的96位整数,与保存在寄存器R4、R5和R6内的96位整数相减,结果保存在寄存器R4、R5和R6中。使用SUBS和SBCS指令实现该96位整数相减功能。


视频讲解


5.9逻辑操作指令
本节介绍逻辑操作指令,下面对这些指令进行详细说明。
1. ANDS <Rd>, <Rm>
该指令将寄存器Rd和寄存器Rm中的内容做“逻辑与”运算,结果保存在寄存器Rd中,同时更新寄存器APSR中的标志N、Z和C,但不更新标志V。该汇编助记符指令的机器码格式如图5.50所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.50ANDS <Rd>, <Rm>指令的机器码格式


指令ANDS R0, R1的机器码为(4008)16。该指令将寄存器R0和寄存器R1中的内容做“逻辑与”运算,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
2. ORRS <Rd>, <Rm>
该指令将寄存器Rd和寄存器Rm中的内容做“逻辑或”运算,结果保存在寄存器Rd中,同时更新寄存器APSR中的N、Z和C标志,但不更新标志V。该汇编助记符指令的机器码格式如图5.51所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.51ORRS<Rd>, <Rm>指令的机器码格式


指令ORRS R0, R1的机器码为(4308)16。该指令将寄存器R0和寄存器R1中的内容做“逻辑或”运算,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
3. EORS <Rd>, <Rm>
该指令将寄存器Rd和寄存器Rm中的内容做“逻辑异或”运算,结果保存在寄存器Rd中,同时更新寄存器APSR中的标志N、Z和C,但不更新标志V。该汇编助记符指令的机器码格式如图5.52所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.52EORS<Rd>, <Rm>指令的机器码格式


指令EORS R0, R1的机器码为(4048)16。该指令将寄存器R0和寄存器R1中的内容做“逻辑异或”运算,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
4. MVNS <Rd>, <Rm>
该指令将寄存器Rm的[31:0]位按位做“逻辑取反”运算,结果保存在寄存器Rd中,同时更新寄存器APSR中的标志N、Z和C,但不更新标志V。该汇编助记符指令的机器码格式如图5.53所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.53MVNS<Rd>, <Rm>指令的机器码格式


指令MVNS R0, R1的机器码为(43C8)16。该指令将寄存器R1的[31:0]位按位做“逻辑取反”运算,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
5. BICS <Rd>, <Rm>
该指令将寄存器Rm的[31:0]位按位做“逻辑取反”运算,然后与寄存器Rd中的[31:0]位做“逻辑与”运算,结果保存在寄存器Rd中,同时更新寄存器APSR中的标志N、Z和C,但不更新标志V。该汇编助记符指令的机器码格式如图5.54所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.54BICS <Rd>, <Rm>指令的机器码格式


指令BICS R0, R1的机器码为(4388)16。该指令将寄存器R1的[31:0]位按位做“逻辑取反”运算,然后与寄存器R0 中的[31:0]位做“逻辑与”操作,结果保存在寄存器R0中,同时更新寄存器APSR中的标志。
6. TST <Rd>, <Rm>
该指令将寄存器Rd和寄存器Rm中的内容做“逻辑与”运算,但是不保存结果,同时更新寄存器APSR中的标志N、Z和C,但不更新标志V。该汇编助记符指令的机器码格式如图5.55所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.55TST<Rd>, <Rm>指令的机器码格式


指令TST R0, R1的机器码为(4208)16。该指令将寄存器R0和寄存器R1中的内容做“逻辑与”运算,但是不保存结果,并且更新寄存器APSR中的标志。
思考与练习510: 说明下面指令所实现的功能。
(1) ANDS R2, R2, R1
(2) ORRS R2, R2, R5
(3) ANDS R5, R5, R8
(4) EORS R7, R7, R6
(5) BICS R0, R0, R1


视频讲解


5.10移位操作指令
本节介绍右移和左移操作指令,下面对这些指令进行详细介绍。
5.10.1右移指令
1. ASRS <Rd>, <Rm>

该指令执行算术右移操作。将保存在寄存器Rd中的数据向右移动Rm所指定的次数,移位的结果保存在寄存器Rd中,即Rd=RdRm。在右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。在算术右移时,最高位的规则如图5.56(a)所示。


图5.56算术和逻辑右移操作 


该汇编助记符指令的机器码格式如图5.57所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.57ASRS <Rd>, <Rm>指令的机器码格式


指令ASRS R0, R1的机器码为(4108)16。该指令将保存在寄存器R0中的数据向右移动R1所指定的次数,移位的结果保存在寄存器R0中。在右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。
2. ASRS <Rd>, <Rm>, #imm
该指令执行算术右移操作。将保存在寄存器Rm中的数据向右移动立即数imm所指定的次数,移位的结果保存在寄存器Rd中。在右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。该汇编助记符指令的机器码格式如图5.58所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.58ASRS <Rd>, <Rm>, #imm指令的格式


注: (1) 汇编指令中立即数imm的范围为1~32。
(2) 当imm<32时,imm5=imm; 当imm=32时,imm5=0。
指令ASRS R0, R1,#0x01的机器码为(1048)16。该指令将保存在寄存器R1中的数据向右移动1次,移位的结果保存在寄存器R0中。在右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。
3. LSRS <Rd>, <Rm>
该指令执行逻辑右移操作。将保存在寄存器Rd中的数据向右移动Rm所指定的次数,移位的结果保存在寄存器Rd中。在右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。在逻辑右移时,最高位的规则如图5.56(b)所示。该汇编助记符指令的机器码格式如图5.59所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.59LSRS <Rd>, <Rm>指令的机器码格式


指令LSRS R0, R1的机器码为(40C8)16。该指令将保存在寄存器R0中的数据向右移动R1所指定的次数,移位的结果保存在寄存器R0中。在右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。
4. LSRS <Rd>, <Rm>, #imm
该指令执行逻辑右移操作。将保存在寄存器Rm中的数据向右移动立即数#imm所指定的次数,移位的结果保存在寄存器Rd中。在右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。该汇编助记符指令的机器码格式如图5.60所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.60LSRS <Rd>, <Rm>, #imm指令的机器码格式


注: (1) 汇编指令中立即数imm的范围为1~32。
(2) 当imm<32时,imm5=imm; 当imm=32时,imm5=0。
指令LSRS R0, R1, #0x01的机器码为(0848)16。该指令将保存在寄存器R1中的数据向右移动1次,移位的结果保存在寄存器R0中。在右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。
5.RORS <Rd>, <Rm>
该指令执行循环右移操作。将保存在寄存器Rd中的数据向右循环移动Rm所指定的次数,移位的结果保存在寄存器Rd中。在循环右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。循环右移的规则如图5.61所示。该汇编助记符指令的机器码格式如图5.62所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.61循环右移操作 




图5.62RORS <Rd>, <Rm>指令的机器码格式


指令RORS R0, R1的机器码为(41C8)16。该指令将保存在寄存器R0中的数据向右循环移动R1所指定的次数,移位的结果保存在寄存器R0中。在循环右移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。
5.10.2左移指令
1. LSLS <Rd>, <Rm>

该指令执行逻辑左移操作。将保存在寄存器Rd中的数据向左移动Rm所指定的次数,移位的结果保存在寄存器Rd中。在左移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。逻辑左移的规则如图5.63所示。该汇编助记符指令的机器码格式如图5.64所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.63逻辑左移操作 




图5.64LSLS <Rd>, <Rm>指令的机器码格式


指令LSLS R0, R1的机器码为(4088)16。该指令将保存在寄存器R0中的数据向左移动R1所指定的次数,移位的结果保存在寄存器R0中。在左移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。
2. LSLS <Rd>, <Rm>, #imm
该指令执行逻辑左移操作。将保存在寄存器Rd中的数据向左移动立即数imm所指定的次数,移位的结果保存在寄存器Rd中,在左移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。该汇编助记符指令的机器码格式如图5.65所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.65LSLS <Rd>, <Rm>, #imm指令的机器码格式


注: imm5与imm之间的关系见LSRS指令。
指令LSLS R0, R1, #0x01的机器码为(0048)16。该指令将保存在寄存器R1中的数据向左移动1次,移位的结果保存在寄存器R0中。在左移过程中,最后移出去的位保存在寄存器APSR的C标志中,也更新N和Z标志。
思考与练习511: 说明下面指令所实现的功能。
(1) ASRS R7, R5, #9
(2) LSLS R1, R2, #3
(3) LSRS R4, R5, #6
(4) RORS R4, R4, R6


视频讲解


5.11反序操作指令


图5.66REV操作 

本节介绍反序操作指令,下面对这些指令进行详细说明。
1. REV <Rd>, <Rm>
该指令将寄存器Rm中字节的顺序按逆序重新排列,结果保存在寄存器Rd中,如图5.66所示。该汇编助记符指令的机器码格式如图5.67所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.67REV <Rd>, <Rm>指令的机器码格式


指令REV R0, R1的机器码为(BA08)16。该指令将寄存器中R1的数据逆序重新排列{R1[7:0],R1[15:8],R1[23:16],R1[31:24]},结果保存在寄存器R0中。


图5.68REV16操作

2. REV16 <Rd>, <Rm>
该指令将寄存器Rm中的内容以半字为边界,半字内的两个字节逆序重新排列,结果保存在寄存器Rd中,如图5.68所示。该汇编助记符指令的机器码格式如图5.69所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.69REV16 <Rd>, <Rm>指令的机器码格式




图5.70REVSH操作 


指令REV16 R0, R1的机器码为(BA48)16。该指令将寄存器中R1的数据以半字为边界,半字内的字节按逆序重新排列,即{R1[23:16],R1[31:24],R1[7:0],R1[15:8]},结果保存在寄存器R0中。
3. REVSH <Rd>, <Rm>
该指令将寄存器Rm中的低半字内的两个字节逆序重新排列,结果保存在寄存器Rd[15:0]中,对于Rd[31:16]中的内容由交换字节后R[7]的内容决定,即符号扩展,如图5.70所示。该汇编助记符指令的机器码格式如图5.71所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.71REVSH <Rd>, <Rm>指令的机器码格式


指令REVSH R0, R1的机器为(BAC8)16。该指令将寄存器中R1的低半字内的两字节按逆序重新排列,结果保存在寄存器R0[15:0]中,对于R0[31:16]中的内容由交换字节后R0[7]的内容决定,即符号扩展,表示为: R0=符号扩展{R1[7:0],R1[15:8]}。
思考与练习512: 说明下面指令所实现的功能。
(1) REV R3, R7
(2) REV16 R0, R0
(3) REVSH R0, R5


视频讲解


5.12扩展操作指令
本节介绍扩展操作指令,下面对这些指令进行详细说明。
1. SXTB <Rd>, <Rm>
将寄存器Rm中的[7:0]进行符号扩展,结果保存在寄存器Rd中。该汇编助记符指令的机器码格式如图5.72所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.72SXTB <Rd>, <Rm>指令的机器码格式


指令SXTB R0, R1的机器码为(B248)16。该指令将寄存器R1中的[7:0]进行符号扩展,结果保存在寄存器R0中,表示为R0=符号扩展{R1[7:0]}。
2. SXTH <Rd>, <Rm>
将寄存器Rm中的[15:0]进行符号扩展,结果保存在寄存器Rd中。该汇编助记符指令的机器码格式如图5.73所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.73SXTH <Rd>, <Rm>指令的机器码格式


指令SXTH R0, R1的机器码为(B208)16。该指令将寄存器R1中的[15:0]进行符号扩展,结果保存在寄存器R0中,表示为R0=符号扩展{R1[15:0]}。
3. UXTB <Rd>, <Rm>
将寄存器Rm中的[7:0]进行零扩展,结果保存在寄存器Rd中。该汇编助记符指令的机器码格式如图5.74所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.74UXTB <Rd>, <Rm>指令的机器码格式


指令UXTB R0, R1的机器码为(B2C8)16。该指令将寄存器R1中的[7:0]进行零扩展,结果保存在寄存器R0中,表示为R0=零扩展{R1[7:0]}。
4. UXTH <Rd>, <Rm>
将寄存器Rm中的[15:0]进行零扩展,结果保存在寄存器Rd中。该汇编助记符指令的机器码格式如图5.75所示。可以看出,寄存器Rm和Rd的范围为R0~R7。


图5.75UXTH <Rd>, <Rm>指令的机器码格式


指令UXTH R0, R1的机器码为(B288)16。该指令将寄存器R1中的[15:0]进行零扩展,结果保存在寄存器R0中,表示为R0=零扩展{R1[15:0]}。
思考与练习513: 说明下面指令所实现的功能。
(1) SXTH R4, R6
(2) UXTB R3, R1


视频讲解


5.13程序流控制指令
本节介绍程序流控制指令,下面对这些指令进行详细说明。
1. B <label>
实现无条件跳转,该汇编助记符指令的机器码格式如图5.76所示。


图5.76B <label>指令的机器码格式


注: (1) label是要跳转到的指令的标号。imm11为汇编器计算得到的偏移量,该偏移量允许的范围为-2048~+2046之间的偶数。
(2) 当前B指令的PC值加4,作为计算与目标标号地址之间偏移量的PC值,目标标号的地址减去该PC值得到偏移量,然后将得到的偏移量的值除以2,则是imm11的值。
指令B loop无条件跳转到loop标号地址以执行指令。
2. B <cond> <label>
有条件跳转指令,根据寄存器APSR中的N、Z、C和V标志,跳转到label所标识的地址。该汇编助记符指令的机器码格式如图5.77所示。其中,cond为条件码,其编码格式如表5.3所示。


图5.77B <cond> <label>指令的机器码格式


注: (1) label是要跳转到的指令的标号。imm8为汇编器计算得到的偏移量,该偏移量允许的范围为-256~+254之间的偶数。
(2) 当前B指令的PC值加4,作为计算与目标标号地址之间偏移量的PC值, 目标标号的地址减去该PC值得到偏移量,然后将得到的偏移量的值除以2,则是imm8的值。


表5.3cond的编码格式


cond助记符扩展含义条 件 标 志

0000EQ相等Z=1
0001NE不相等Z=0
0010CS(1)设置进位
C=1
0011
CC(2)
清除进位
C=0
0100
MI
减,负的
N=1
0101
PL
加,正的或零
N=0
0110
VS
溢出
V=1
0111
VC
无溢出
V=0
1000
HI
无符号的较高
C=1且Z=0
1001
LS
无符号的较低或相同
C=0或Z=1
1010
GE
有符号的大于或等于
N=V
1011
LT
有符号的小于
N!=V
1100
GT
有符号的大于
Z=0且N=V
1101
LE
有符号的小于或等于
Z=1或N!=V
1110(3)
None(AL)(4)
总是(无条件)
任何

注: (1) HS(无符号较高或相同)是CS的同义词。
(2) LO(无符号的较低)是CC的同义词。
(3) 永远不会在ARMv6M Thumb指令中对该值进行编码。
(4) AL是为总是而提供的一个可选的助记符扩展名。

指令BEQ loop的功能是: 当寄存器APSR寄存器中的标志位Z等于1时,将跳转到标号为loop的位置执行指令。
注: B指令具体条件的表示参考5.2.3节介绍的后缀含义。
3. BL <label>
该指令表示跳转和链接,跳转到一个地址,并且将返回地址保存到寄存器LR中。跳转地址为当前PC±16M字节的范围内。该指令通常用于调用一个子程序或者函数。一旦完成了函数,通过执行指令BX LR可以返回。
指令中的label是要跳转到的指令的标号。汇编器计算从BL指令的PC值(该PC值加4后才作为计算真正使用的PC值)到该标号的偏移量所需的值,然后选择将imm32设置为该偏移量的编码。允许的偏移量是-16777216~+16777214。
BL指令是Thumb指令集中的32位指令。该汇编助记符指令的机器码格式如图5.78所示。其中:


图5.78BL<label>指令的机器码格式


I1=NOT(J1 EOR S); I2=NOT(J2 EOR S); imm32=SignExtend(S:I1:I2:imm10:imm11:'0',32)。很明显,偏移量地址包括S、I1、I2、imm10和imm11。
注: 在引入Thumb2技术之前,J1和J2均为1,导致分支的范围较小。这些指令可作为两个单独的16位指令执行,第一条指令instr1将LR设置为PC+有符号扩展(instr1 <10:0>: '000000000000',32),第二条指令完成该操作。在ARMv6T2、ARMv6M和ARMv7中,不再可能将BL指令拆分为两个16位指令。
指令BL functionA,该指令将PC值修改为functionA标号所表示的地址值,寄存器LR的值等于PC+4。
4. BX <Rm>
该指令表示跳转和交换,跳转到寄存器所指定的地址,根据寄存器的第0位的值(1表示Thumb,0表示ARM),在ARM和Thumb模式之间切换处理器的状态。ARMv6M仅支持Thumb执行。尝试更改指令执行状态会导致目标地址上指令的异常。该汇编助记符指令的机器码格式如图5.79所示。可以看出,寄存器Rm可用的范围为R0~R15。


图5.79BX <Rm>指令的机器码格式


指令BX R0的机器码为(4700)16。该指令将PC值修改为R0寄存器内的内容即PC=R0。
5. BLX <Rm>
跳转和带有交换的链接。跳转到寄存器所指定的地址,将返回地址保存到寄存器LR中,并且根据寄存器的第0位的值(1表示Thumb,0表示ARM),在ARM和Thumb模式之间切换处理器的状态。ARMv6M仅支持Thumb执行。尝试更改指令执行状态会导致目标地址上指令的异常。
注: 返回地址=当前指令的PC值+4-2=当前指令的PC值+2,第0位需要设置为1。
该汇编助记符指令的机器码格式如图5.80所示。可以看出,寄存器Rm可用的范围为R0~R15。


图5.80BLX <Rm>指令的机器码格式



指令BLX R0的机器码为(4780)2。该指令将PC值修改为R0寄存器内的内容,即PC=R0,并且寄存器LR的值等于当前PC+2(LR的第0位应该为1,以保持Thumb状态)。
思考与练习514: 说明下面指令所实现的功能。
(1) B loopA
(2) BL funC
(3) BX LR
(4) BLX R0
(5) BEQ labelD





视频讲解


5.14存储器屏障指令
本节介绍存储器屏障指令,下面对这些指令进行详细说明。
1. DMB
数据存储器屏蔽指令(Data Memory Barrier,DMB)。在提交新的存储器访问之前,确保已经完成所有的存储器访问。DMB指令是Thumb指令集上的32位指令。该汇编助记符指令的机器码格式如图5.81所示。


图5.81DMB指令的机器码格式


注: option指定DMB操作的可选限制。SY DMB操作可以确保所有访问的顺序,option编码为1111。可以省略。保留option的所有其他编码。相应指令执行系统(SY)DMB操作,但是软件不依赖该行为。
2. DSB
数据同步屏蔽指令(Data Synchronization Barrier,DSB)。在执行下一条指令前,确保已经完成所有的存储器访问。DSB指令是Thumb指令集上的32位指令。该汇编助记符指令的机器码格式如图5.82所示。


图5.82DSB指令的机器码格式


注: option指定DSB操作的可选限制。SY DMB操作可以确保完成所有的访问,option编码为1111。可以省略。保留option的所有其他编码。相应指令执行系统(SY)DSB操作,但是软件不依赖该行为。
3. ISB
指令同步屏蔽指令(Instruction Synchronization Barrier,ISB)。在执行新的指令前,刷新流水线,确保已经完成先前所有的指令。ISB指令是Thumb指令集上的32位指令。该汇编助记符指令的机器码格式如图5.83所示。


图5.83ISB指令的机器码格式


注: option指定ISB操作的可选限制。完整的系统ISB操作,option编码为1111。可以省略。保留option的所有其他编码。相应指令执行完整的系统ISB操作,但是软件不依赖该行为。


视频讲解


5.15异常相关指令
本节介绍异常相关指令,下面对这些指令进行详细说明。
1. SVC #<imm8>
管理员调用指令,触发SVC异常。该汇编助记符指令的机器码格式如图5.84所示。


图5.84SVC #<imm8>指令的机器码格式


指令SVC #3的机器码为(DF03)16。该指令表示触发SVC异常,其参数为3。
2. CPS<effect> i
该指令修改处理器的状态,使能/禁止中断,该指令不会阻塞NMI和硬件故障句柄。该指令中的<effect>指定对PRIMASK所要求的效果。<effect>为下面其中之一: 
(1) IE。中断使能,将PRIMASK.PM设置为0。
(2) ID。中断禁止,将PRIMASK.PM设置为1。
指令中的i表示PRIMASK受到的影响。当设置为1时,将当前优先级提高为0。PRIMASK是1位寄存器,只能从特权级执行中访问它。该汇编助记符指令的机器码格式如图5.85所示。


图5.85CPS<effect> i指令的机器码格式


指令CPSIE i的机器码为(B662)16,该指令使能中断,清除PRIMASK; 指令CPSID i的机器码为(B672)16,该指令禁止中断,设置PRIMASK。


视频讲解



5.16休眠相关指令
本节介绍与休眠状态相关的指令,下面对这些指令进行详细说明。
1. WFI
该指令等待中断,停止执行程序,直到中断到来或者处理器进入调试状态。该汇编助记符指令的机器码格式如图5.86所示。


图5.86WFI指令的机器码格式


2. WFE
该指令等待事件,停止执行程序,直到事件到来(由内部事件寄存器设置)或者处理器进入调试状态。该汇编助记符指令的机器码格式如图5.87所示。


图5.87WFE指令的机器码格式


3. SEV
在多处理环境(包括自身)中,向所有处理器发送事件。该汇编助记符指令的机器码格式如图5.88所示。


图5.88SEV指令的机器码格式





视频讲解


5.17其他指令
本节介绍其他指令,下面进行详细说明。
1. NOP
该指令为空操作指令,该指令用于产生指令对齐,或者引入延迟。该汇编助记符指令的机器码格式如图5.89所示。


图5.89NOP指令的机器码格式


2. BKPT #<imm8>
该指令为断点指令,将处理器置位停止阶段。指令中的imm8标识保存在指令中的一个8位数。ARM硬件忽略这个值,但是调试器可以用它来保存关于断点的额外信息。
在该阶段,通过调试器,用户执行调试任务。由调试器插入BKPT指令,用于代替原来的指令。该汇编助记符指令的机器码格式如图5.90所示。


图5.90BKPT #<imm8>指令的机器码格式


指令BKPT #5的机器码格式为(BE05)16,该指令表示标号为5的断点。
3. YIELD
YIELD是一个提示指令。它使具有多线程功能的软件能够向硬件指示其正在执行任务(例如自旋锁),可以将其交换以提高系统的整体性能。
如果硬件支持该功能,则可以使用它提示挂起和恢复多个代码线程。该汇编助记符指令的机器码格式如图5.91所示。


图5.91YIELD指令的机器码格式