ARM指令分类

ARM指令分类

ARM 指令集

分支指令

在 ARM 中有两种方式可以实现程序的跳转:
一种是使用分支转移指令直接跳转;
另一种则是直接向 PC 寄存器赋值来实现跳转。
ARM 的分支转移指令,可以从当前指令向前或向后的 32MB($2^{23}\times4=2^{10} \times 2^{10} \times 32 $) 的地址空间跳转,根据完成的功能它可以分为 4 种:BBLBXBLX

signed_immed_24 间接提供目标地址,真正的目标地址是由处理器根据这个有符号数和当前的 PC 值计算出来的。
具体计算为:先将 signed_immed_24 左移两位(即具有 26 位的偏移量),并扩展为 32 位有符号数,然后再将这 32 位有符号数与 PC 的当前值相加,得到实际的跳转地址。
因此 B 和 BL 指令转移的偏移量为 26 位,即转移的跨度为前后 32MB 地址空间。

跳转指令 B 及带连接的跳转指令 BL

B指令与BL指令的编码格式如下:

从编码中看到 L 控制了 PC 与 LR 寄存器之间的开关。当 L=0 时,该开关断开,指令为 B 指令;当 L=1 时,该开关接通,指令为 BL 指令。
Signed_immed_24 表示 24 位有符号的立即数(偏移量)

B 和 BL 指令的助记符格式为:
B {<cond>} <target>和BL{<cond>} <target>
cond 表示指令执行条件
target 表示跳转地址
功能:跳转到指定地址执行,地址范围限制在当前 PC 寄存器所指向的指令地址的 ±32MB 范围

跳转指令也叫程序转移指令。
写汇编程序时,可以跳转到一个绝对地址,如:
B 0x1234 (注: B #0x1234 是错误的 )
编译器会把该绝对地址转换为相对地址放入指令中。

1
2
3
4
5
6
7
例:现已知寄存器 R0 中存放了数据 a ,寄存器 R1 中存放了数据 b ,编写一个程序段,求取 a 和 b 的最大公约数并将其存入寄存器 R0 。
gcb CMP R0,R1 ; 比较a和b的大小
SUBGT R0,R0,R1; 如果a>b,则a=a-b
SUBLT R1,R1,R0; 如果a<b,则b=b-a
BNE gcb ; 如果a!=b,则返回gcb
MOV PC,LR ; 如果a=b,则返回主程序

B(Branch)和 BL(Branch with Link) 的区别在于:BL 在跳转之前会把 BL 指令的下一条指令地址(断点地址)保存到连接寄存器 LR(R14),因此程序在必要的时候可以通过将 LR 的内容加载到 PC 中,使程序返回到跳转点。
BL 这也是一个跳转指令,但它在跳转之前会将下一条指令的地址存储到链接寄存器(LR)中。这是为了在子程序或函数执行完毕后,能够返回到调用它的代码处继续执行。换句话说,BL 指令用于函数或子程序的调用。

1
2
3
4
5
6
7
8
9
10
11
_start:
MOV R0, #5 ; 将5放入寄存器R0
BL multiply ; 调用multiply函数
B end ; 跳转到end标签

multiply:
LSL R0, R0, #1 ; 将R0的值乘以2(逻辑左移)
MOV PC, LR ; 返回到调用multiply的地方

end:
; 这里是程序结束的地方

带状态切换的跳转指令 BX

BX 指令的格式为BX{<cond>} Rm

cond 表示指令执行条件
Rm 寄存器,值是绝对地址值,不是偏移量,在指令执行后,Rm 中的地址值与#0XFFFF FFFE 进行 AND 运算,再被复制到程序计数器 PC。
带状态切换的跳转。最低位(Rm[0])为 1 时,切换到 Thumb 指令执行,为 0 时,解释为 ARM 指令执行

1
2
3
4
5
6
7
8
9
10
11
12
例如:
CODE32 ;32位编码
ARM1 LDR R0=Thumb1 ;把Thumb地址赋给R0,末位自动置1
MOV LR,PC ;设置返回地址
BX R0 ;跳转,切换状态
ADD R1,R2,#2

CODE16 ;16位编码
Thumb1 ADD R1R3,#1 ;Thumb程序

BX LR ;跳转到返回地址,状态切换

带连接和状态切换的连接跳转指令 BLX

 BLX 指令的格式有两种:

BLX <target> 和 BLX{<cond>} Rm
以 target 方式提供目标地址的 BLX 指令的功能是:把程序跳转到指令中所指定的目标地址继续执行,并同时将处理器的工作状态从 ARM 状态切换到 Thumb 状态,并将下一条的地址保存到寄存器 LR 中。
而以 Rm 方式提供目标地址的 BLX 指令,除了跳转和下一条的地址保存到 LR 之外,也可进行状态切换,但其切换的依据是 Rm 最低位的值。如果值为 0 ,则目标地址处应为 ARM 指令,如果值为 1 ,则目标地址处应为 Thumb 指令

修改 PC

另一种实现指令跳转的方式是通过直接向 PC 寄存器中写入目标地址值,实现在 4GB 地址空间中任意跳转,这种跳转又称为长跳转。
如果在长跳转指令之前使用“MOV LR,PC” 等指令,可以保存将来返回的地址值,也就实现了在 4GB 的地址空间中的子程序调用。

数据处理指令

数据处理指令概述

1. ARM 数据处理指令的功能
主要完成寄存器中数据的算术和逻辑运算操作。
2. ARM 数据处理指令的特点
操作数来源:所有的操作数要么来自寄存器,要么来自立即数,不会来自存储器。
操作结果:如果有结果,则结果一定是为 32 位宽、或 64 位宽(长乘法指令),并且放在一个或两个寄存器中,不会写入存储器。
有第二个操作数 Operand2 :切记其三种形式:立即数、寄存器、寄存器移位。特别地,乘法指令的操作数:全部是寄存器。

3. ARM 数据处理指令分类
算术运算指令:ADD ADC SUB SBC RSB RSC MUL MLA UMULL UMLAL SMULL SMLAL
逻辑运算指令: AND ORR EOR BIC
数据传送指令: MOV MVN
比较指令: CMP CMN
测试指令: TST TEQ
上述指令只能对寄存器操作,不能针对存储器。

4. 数据处理指令对程序状态寄存器 CPSR 的影响
指令中可以添加 S 后缀,以影响 CPSR 状态标志。但是比较指令(CMP 和 CMN)和测试指令(TST 和 TEQ)不需要后缀 S,它们总会直接影响 CPSR 中的状态标志。

关于恢复 CPSR 原值问题:

如果指令带有 S 后缀(除了比较指令以外),同时又以 PC 为目标寄存器进行操作:
1. 在异常模式下:则操作的同时从 SPSR(Saved Program Status Register) 恢复 CPSR(Current Program Status Register)

1
2
3
4
movs pc, #0xff	/* cpsr = spsr; pc = 0xff */
adds pc, r1, #0xff00
/* cpsr = spsr; pc = r1 + 0xff00 */
ands pc, r1, r2 /* cpsr = spsr; pc = r1 & r2; */

2. 在 user 或者 system 模式:会产生不可预料的结果,因为在这两种模式下没有 SPSR

数据处理指令格式

I 用于区别立即数(I=1)或寄存器移位(I=0)
opcode 为数据处理指令操作码
operand2 为第二个操作数,若指令不需要全部的可用操作数时(如 MOV 指令的 Rn),不用的寄存器域应设置为 0(由编译器自动完成)。对于比较指令,b20 位固定为 1。

Data Processing Instructions

加减乘

ADD——加法运算指令
ADD{cond}{S} Rd,Rn,operand2; Rd<-Rn+operand2

受影响的 CPSR 标志位 取值
N 寄存器 Rd[31]被复制到 N
Z 如果 Rd 为 0,则 Z=1,否则 Z=0
C 运算结果有进位 C=1,否则 C=0
V 运算结果有溢出 V=1,否则 V=0
1
2
3
ADD R0,R1,R2  	  	;R0←(R1)+(R2)
ADD R0,R1,#255 ;R0 ←(R1)+ 255
ADD R0,R2,R3,LSL#1 ;R0 ←(R2) +(R3<<1)

ADC——带进位加法指令
指令格式:ADC{cond}{S} Rd,Rn,operand2
ADC 指令将 operand2 的数据与 Rn 的值相加,再加上 CPSR 中的 C 条件标志位,结果保存到 Rd 寄存器。
ADC 通常用来实现字长大于 32 位的加法运算。

SUB——减法运算指令
指令格式:SUB{cond}{S} Rd,Rn,operand2
SUB 指令用寄存器 Rn 减去 operand2,结果保存到 Rd 中

1
2
3
SUB R0,R1,R2 ;R0←(R1)-(R2)
SUB R0,R1,#256;R0←(R1)- 256
SUB R0,R2,R3,LSL#1;R0←(R2)-(R3<<1)
受影响的 CPSR 标志位 取值
N 寄存器 Rd[31]被复制到 N
Z 如果 Rd 为 0,则 Z=1,否则 Z=0
C 运算结果有借位 C=0,否则 C=1
V 运算结果有溢出 V=1,否则 V=0

SBC——带进位减法指令
指令格式:SBC{cond}{S} Rd,Rn,operand2
SBC 指令用寄存器 Rn 减去 operand2,再减去 CPSR 中的 C 条件标志位的反码,结果保存到 Rd 中。
标志位的修改同 SUB。该指令主要用于字长大于 32 位的数据的减法运算。

RSC——带进位反向减法指令
指令格式:RSC{cond}{S} Rd,Rn,operand2
RSC 指令用寄存器 operand2 减去 Rn,再减去 CPSR 中的 C 条件标志位的反码,结果保存到 Rd 中。

乘法指令格式

其中,opcode 为乘法指令操作码。S 为设置条件码。Rm 为被乘数寄存器,Rs 为乘数的寄存器。Rn/RdLo 用于 MLA 指令相加的寄存器或 64 位乘法指令的目标寄存器(低 32 位)。Rd/RdHi 用于目标寄存器或 64 位乘法指令的目标寄存器(高 32 位)。若指令不需要全部的可用操作数时(如 MUL 指令的 Rn),不用的寄存器域应设置为 0(由编译器自动完成)


MUL——32 位乘法指令
指令格式:MUL{cond}{S} Rd,Rm,Rs
MUL 指令将 Rm 和 Rs 中的值相乘,结果的低 32 位保存到 Rd 中

受影响的 CPSR 标志位 取值
N 寄存器 Rd[31]被复制到 N
Z 如果 Rd 为 0 则 Z=1,否则 Z=0
1
2
3
MUL    R1,R2,R3    ;R1=R2×R3
MULS R0,R3,R7 ;R0=R3×R7,
;设置CPSR的N位和Z位

MLA——32 位乘加指令
格式 MLA{cond}{S} Rd,Rm,Rs,Rn
指令将 Rm 和 Rs 中的值相乘,再将乘积加上第 3 个操作数,结果的低 32 位保存到 Rd 中。注: Rd ≠ Rm
标志位的修改同 MUL。

1
2
3
MLA R0,R1,R2,R3   ;R0←(R1)X(R2)+(R3)
MLAS R0,R1,R2,R3 ; R0←(R1)X(R2)+(R3),
;并更新CPSR标志位

UMULL—64 位无符号乘法指令
指令格式:UMULL{cond}{S} RdLo,RdHi,Rm,Rs;RdHi, RdLo← Rm*Rs
UMULL 指令将 Rm 和 Rs 中的值作无符号数相乘,结果的低 32 位保存到 RdLo 中,高 32 位保存到 RdHi 中
例:UMULL R0,R1,R5,R8;(R1,R0)←R5×R8

受影响的 CPSR 标志位 取值
N 寄存器 RdHi[31]被复制到 N
Z 如果 RdHi 且 Rdlo 为 0,则 Z=1,否则 Z=0

UMLAL—64 位无符号乘加指令
指令格式:UMLAL{cond}{S} RdLo,RdHi,Rm,Rs;RdHi, RdLo← Rm*Rs+ RdHi, RdLo
UMLAL 指令将 Rm 和 Rs 中的值作无符号数相乘,64 位乘积与 RdHi、RdLo 相加,结果的低 32 位保存到 RdLo 中,而高 32 位保存到 RdHi 中。
标志的修改同 UMULL。
指令举例如下:
UMLAL R0,R1,R5,R8;(R1,R0)←R5×R8+(R1,R0)

SMULL—64 位有符号乘法指令
指令格式:SMULL{cond}{S} RdLo,RdHi,Rm,Rs; RdHi, RdLo← Rm*Rs
SMULL 指令将 Rm 和 Rs 中的值作有符号数相乘,结果的低 32 位保存到 RdLo 中,而高 32 位保存到 RdHi 中。
例如:SMULL R2,R3,R7,R6;(R3,R2)←R7×R6

受影响的 CPSR 标志位 取值
N 寄存器 RdHi[31]被复制到 N
Z 如果 RdHi 且 Rdlo 为 0,则 Z=1,否则 Z=0

SMLAL—64 位有符号乘加指令
指令格式:SMLAL{cond}{S} RdLo,RdHi,Rm,Rs; RdHi, RdLo← Rm*Rs+ RdHi, RdLo
SMLAL 指令将 Rm 和 Rs 中的值作有符号数相乘,64 位乘积与 RdHi、RdLo 相加,结果的低 32 位保存到 RdLo 中,高 32 位保存到 RdHi 中。
标志的修改同 SMULL。

乘法指令的特点

  • 结果寄存器不能与第一源寄存器相同。
  • 不支持第 2 操作数为立即数。
  • Rd、RdHi、RdLo 不能与 Rm 为同一寄存器。
  • RdHi 和 RdLo 不能为同一寄存器。
  • 避免将 R15 定义为任一操作数或结果寄存器。
  • 早期的 ARM 处理器仅支持 32 位乘法指令。ARM7 版本和后续的在名字中有 M 的处理器才支持 64 位乘法指令。
  • 对标志位的影响
    • 对 N 标志位:若结果是 32 位指令形式,Rd 的第 31 位是标志位 N;对于产生长结果的指令形式,RdHi 的第 31 位是标志位。
    • 对 Z 标志位:如果 Rd 或 RdHi、RdLo 为 0,则标志位 Z 置位。
    • 对 V 标志位:乘法指令不影响 V 标志位。
    • 对 C 标志位: ARM v5 及以上的版本不影响 C 标志位; ARM v5 以前的版本,C 标志位数值不确定。
逻辑运算指令
  1. 按位与指令(AND)
    按位与指令用于将两个寄存器中的值进行按位与运算,并将结果存储在目标寄存器中。基本语法如下:
    AND Rd, Rn, Operand2
    其中,Rd 是目标寄存器,Rn 是第一个操作数所在寄存器,Operand2 是第二个操作数。
    示例:AND R0, R1, R2
    这个指令将 R1 和 R2 中的值进行按位与运算,并将结果存储在 R0 中。

  2. 按位或指令(ORR)
    按位或指令用于将两个寄存器中的值进行按位或运算,并将结果存储在目标寄存器中。基本语法如下:
    ORR Rd, Rn, Operand2
    其中,Rd 是目标寄存器,Rn 是第一个操作数所在寄存器,Operand2 是第二个操作数。
    示例:
    ORR R0, R1, R2
    这个指令将 R1 和 R2 中的值进行按位或运算,并将结果存储在 R0 中。

  3. 按位异或指令(EOR)
    按位异或指令用于将两个寄存器中的值进行按位异或运算,并将结果存储在目标寄存器中。基本语法如下:
    EOR Rd, Rn, Operand2
    其中,Rd 是目标寄存器,Rn 是第一个操作数所在寄存器,Operand2 是第二个操作数。
    示例:
    EOR R0, R1, R2
    这个指令将 R1 和 R2 中的值进行按位异或运算,并将结果存储在 R0 中。

  4. 位清楚指令(BIC)
    按位非指令用于对一个寄存器中的值进行按位取反,并将结果存储在目标寄存器中。基本语法如下:
    BIC Rd, Rn, Operand2
    BIC 指令将寄存器 Rn 的值与 Operand2 的值的反码按位逻辑与操作,结果保存到 Rd 中。
    指令举例如下:
    BIC R1,R1,#0x0F; 将R1的低4位清0,其它位不变

1
2
3
例:请把寄存器R2中的高8位数据传送到寄存器R3的低8位,原R3低24置换为高24位。
MOV R0,R2,LSR #24;将R2右移24位,即将其高8位移至低8位送R0。
ORR R3,R0,R3,LSL #8;将R3左移8位后将R0低8位送至R3。
数据传送指令

MOV{cond}{S} Rd,operand2
MOV 指令将 operand2 传送到目标寄存器 Rd 中

1
2
3
4
MOV R2,#0x7E; 将立即数 0x7E 传送到寄存器 R2 中
MOVS R1,R0,LSL#3; 将寄存器 R0 * 8 传送到寄存器 R1,并影响标志位
MOV PC,LR; PC←LR,子程序返回
MOVS PC,LR; PC←LR,异常模式下返回 CPSR←SPSR

MOV 指令的功能总结

  • 寄存器之间传送。
  • 立即数传送到寄存器中。(8 位立即数位图)
  • 实现单纯的移位操作。MOV Rd,Rd,LSL,#3
  • 实现子程序调用、从子程序中返回。当 PC 寄存器作为目标寄存器时可以实现程序跳转。
  • 实现异常模式的返回,并把当前处理器模式的 SPSR 寄存器内容复制到 CPSR 中。

MVN{cond}{S} Rd,operand2
MVN 指令将 operand2 按位取反后传送到目标寄存器 Rd

比较指令

CMP{cond} Rn,operand2
CMP 指令将寄存器 Rn 的值减去 operand2 的值,但不存储运算结果,只根据操作的结果更新 CPSR 中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。

受影响的 CPSR 标志位 取值
N 运算结果的第 31 位被复制到 N
Z 运算结果为 0 则 Z=1,否则 Z=0
C 运算结果有借位则 C=0,否则 C=1
V 运算结果有溢出则 V=1,否则 V=0

CMN{cond} Rn,operand2
CMN 指令将寄存器 Rn 的值减去 operand2 的相反数(即加上 operand2 的值),但不存储运算结果,只根据操作的结果更新 CPSR 中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。

1
CMN R0,#1;R0+1,判断R0是否为-1。
测试指令

TST{cond} Rn,operand2
TST 指令将寄存器 Rn 的值与 operand2 的值按位逻辑“与”操作,但不存储运算结果,只根据操作的结果更新 CPSR 中的相应条件标志位。该指令一般用来检测是否设置了特定的位。

1
2
TST R0,#0x01;判断 R0 的最低位是否为 0
TST Rl,#0x0F;判断 R1 的低 4 位是否为 0

TEQ{cond} Rn,operand2
TEQ 指令将寄存器 Rn 的值与 operand2 的值按位逻辑“异或”操作,但不存储运算结果,只根据操作的结果更新 CPSR 中的相应条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。
指令举例如下:
TEQ R0,R1;比较 R0 与 R1 是否相等;(不影响 V 位和 C 位)

存储器访问指令

ARM 微处理器用加载/存储指令访问存储器,实现在寄存器和存储器之间传送数据。
由于 ARM 处理器对外设寄存器、I/O 映射空间与存储器统一编址,因此,对外围设备的 I/O 操作也用此类指令。
基本的加载/存储指令仅有 5 条,分为 3 种:

  • LDR 和 STR,单寄存器加载/存储指令
  • LDM 和 STM,多寄存器加载/存储指令
  • SWP,寄存器和存储器数据交换指令


其中,I、P、U、W 用于区别不同的地址模式(偏移量)

  • I 为 0 时,偏移量为 12 位立即数;I 为 1 时,偏移量为寄存器移位;
  • P 表示前/后变址,U 表示加/减,W 表示回写(!后缀)
  • L 用于区别加载(L 为 1 时)或存储(L 为 0 时)
  • B 用于区别字节访问(B 为 1 时)或字访问(B 为 0 时)
  • Rn 为基址寄存器,Rd 为源/目标寄存器。

单寄存器加载/存储指令

单寄存器加载/存储指令是 ARM 在寄存器存储器间传送单个字节和字的最灵活方式。

LDR(Load Register):这是一个加载指令,用于从内存中读取数据并将其加载到寄存器中。其基本格式为 LDR Rd, [Rn],其中 Rd 是目标寄存器,Rn 是包含要读取的内存地址的寄存器;例如,LDR R1, [R2] 会将存储在 R2 寄存器所指向的内存地址中的数据加载到 R1 寄存器中。
STR(Store Register):这是一个存储指令,用于将寄存器中的数据写入到内存中。其基本格式为 STR Rd, [Rn],其中 Rd 是源寄存器,Rn 是包含要写入的内存地址的寄存器。例如,STR R1, [R2] 会将 R1 寄存器中的数据存储到 R2 寄存器所指向的内存地址中。

根据传送数据的类型不同,单个寄存器存取指令又可以分为以下两类:
单字和无符号字节的加载/存储指令
半字和有符号字节的加载/存储指令

单字和无符号字节的加载/存储指令

LDR:指令从内存中取 32 位字或 8 位无符号字节数据放入寄存器;
STR:指令将寄存器中的 32 位字或 8 位无符号字节数据保存到存储器中。

注意:无符号字节加载时,用 0 将 8 位的操作数扩展到 32 位。

Instruction Format
LDR{cond}{T} Rd,<地址>;加载指定地址上的字数据,放入 Rd 中。
STR{cond}{T} Rd,<地址>;存储 Rd 中字数据,到指定地址的存储单元。
LDR{cond}B{T} Rd,<地址>;加载字节数据到 Rd 低 8 位数据位中,高 24 位为 0。
STR{cond}B{T} Rd,<地址>;存储 Rd 中字节数据, Rd 中最低字节为传送数据

Postfix
T 为可选后缀,若指令有 T,存储系统将访问看成是处理器是在用户模式下。
用于存储器保护。
不能与后变址模式、自动变址模式一起使用(即不能改变基址寄存器值)。
T 在用户模式下无效

Addressing
LDR/STR 指令为基址变址寻址[ARM/Ch3-1ARM指令概述.md#基址变址寻址 Base-index Addressing](或寄存器间接寻址),由两部分组成:

  • 基地址部分:为一个基址寄存器,可以为任一个通用寄存器;
  • 偏移地址部分:这一部分非常灵活,实际就类似第二个操作数,可以有以下 3 种格式:
    • 立即数:12 位立即数是一个无符号的数值。这个数据可以加到基址寄存器,也可以从基址寄存器中减去这个数值
    • 寄存器:寄存器中的数值(无符号数)可以加到基址寄存器,也可以从基址寄存器中减去这个数值
    • 寄存器及移位常数:寄存器移位后的值(无符号数)可以加到基址寄存器,也可以从基址寄存器中减去这个数值
      1
      2
      3
      4
      5
      6
      LDR R1,[R0,#0x10];
      LDR R1,[R0,# -0x10];
      LDR R1,[R0,R2]
      LDR R1,[R0,-R2]
      LDR R1,[R0,R2,LSL #2] 将R0+R2×4地址处的数据读出,保存到R1中(R0、R2的值不变)
      LDR R1,[R0,-R2,LSL #2] 将R0-R2×4地址处的数据读出,保存到R1中(R0、R2的值不变)

      PC(即 R15)使用的几个问题
      使用 PC 作为基址时,使用的数值是当前执行指令的地址加 8 个字节(取指与执行相差 8 个字节)。
      PC 不能用做偏移寄存器,也不能用于任何变址寻址模式。
      把一个字加载到 PC,将使程序转移到所加载的地址,这是一个公认的实现跳转的方法。但是应当避免将一个字节加载到 PC。
      把 PC 存到存储器的操作在不同体系结构的处理器中产生不同的结果,应尽可能避免。

多寄存器的存取指令

LDM 和 STM 指令可以实现在一组寄存器和一块连续的内存单元之间存/取数据。
LDM 为加载多个寄存器;STM 为存储多个寄存器。
这两条指令,允许传送 16 个寄存器 R0—R15 的任何子集或所有寄存器。

LDM{cond}<模式> Rn{!},<reglist>{^}
STM{cond} <模式> Rn{!},<reglist>{^}
(1)Rn:表示基址寄存器,装有传送数据的初始地址,Rn 不允许为 R15(即 PC)。
(2)Rn 后缀“!”:表示最后的地址写回到 Rn 中。
(3)Reglist:表示寄存器列表,其中包含一个或多个寄存器。当寄存器不连续时,中间使用“,”隔开。例如:{R1,R2,R6-R9}
列表寄存器和存储器地址的关系规则:编号低的寄存器对应于存储器中低地址单元,编号高的寄存器对应于存储器中高地址单元。
(4)后缀“^”说明
寄存器列表不包含 PC:使用后缀“^”进行数据传送时,加载/存储的是用户模式的寄存器,而不是当前模式的寄存器。
寄存器列表包含有 PC:除了正常的多寄存器传送外,还要将 SPSR 拷贝到 CPSR 中。该用法可用于异常处理返回。
禁用情况:后缀“^”不允许在用户模式或系统模式下使用。 ,因为它们没有 SPSR
(5)当 Rn 在寄存器列表中且使用后缀“!”
对于 STM 指令,若 Rn 为寄存器列表中的最低序号的寄存器,则会将 Rn 的初值保存;
其它情况下 Rn 的编译无法通过。
(6)地址字对齐
这些指令寻址是字对齐的,即忽略地址位[1:0]。

协处理器指令

杂项指令

主要由两种类型指令组成,程序状态寄存器操作指令、中断操作指令,一共有 5 条指令。

状态寄存器操作指令:
MRS:读程序状态寄存器指令
MSR:写程序状态寄存器指令
异常中断操作指令:
SWI: 软件中断指令
BKPT:断点指令(v5T 体系)
CLZ: 前导 0 计数(v5T 体系)

Author

Efterklang

Posted on

2024-03-24

Updated on

2024-09-19

Licensed under

Comments