第三章 ARM7指令系统【嵌入式系统】
前言
2023-7-3 17:05:04
以下内容源自《【嵌入式系统】》
仅供学习交流使用
推荐
第三章 ARM7指令系统
3.1. ARM7TDMI 指令集概述
3.1.1 ARM 指令分类
ARM 指令集属于加载/存储型,即指令仅能处理 CPU 内部寄存器中的数据,而且处理
结果也要放回寄存器中,对于内存或接口中的数据,只能通过加载/存储指令将数据加载到
CPU 内部的寄存器中进行处理,处理结果也只能通过存储指令将寄存器中的数据放回到内
存或接口中。
ARM 处理器的指令集可分为数据处理指令、分支指令、加载/存储指令、交换指令、程
序状态寄存器(PSR)处理指令、协处理指令和异常产生指令七大类,ARM 的基本指令及
功能如表 3-1 所示。
3.1.2 指令格式
1.指令的机器编码格式
在 ARM 指令集中,每条指令占有 4 个字节,即指令长度为 32 位,其指令的二进制编
码格式如图 3.1 所示
其中:
Cond 为指令执行的条件。
Opcode 为数据处理指令/程序状态寄存器(PSR)处理指令的操作编码。在访问指令中
表示是否为有符号数访问。
Rn 为第一操作数,Operand2 为第二操作数,Rd 为目的操作数。
Rs、Rm 分别为乘法指令中的乘数和被乘数。
RdHi、RdLo 分别为长乘法指令乘积的高 32 位寄存器和低 32 位寄存器。
在乘法指令中 A 表示乘加指令,U 表示带符号数的乘法。
S 在数据处理指令中设置是否影响程序状态寄存器中的条件标志位。
I 是 Operand2 的类型制定,I 为 0 时,偏移量为 12 位立即数,为 1 时,偏移量为带移
位的寄存器。
在加载/存储指令中,B 表示字节访问。P 表示前/后变址。W 表示写回。U 表示变址为
加/减。L 用于区别加载(L 为 1)或存储(L 为 0)。
Cp opc 为协处理器的操作编码。
2.指令的汇编格式
在汇编程序设计中,ARM 指令采用三地址的指令格式,即一个目的操作数和两个源操
作数,汇编指令的基本组成如下:
<指令助记符>{<执行条件>}{S} <目标寄存器>, <第 1 操作数的寄存器> {,<第 2 操作数>}
< opcode> {< cond>} {S} < Rd> , < Rn> {,< operand2>}
其中,< >号内的项是必需的,{}号内的项是可选的。如是指令助记符,是必
须含有的,而{}为指令执行条件,是依据实际需要可选项。若不书写,则使用默认条
件 AL(无条件执行)。
opcode 指令助记符,如 LDR、STR 等。用于指定指令的操作功能。
cond 执行条件,如 EQ、NE 等,参考表 3-2。用于指定指令的执行条件。
S 指定指令执行是否影响 CPSR 寄存器中的条件标志位,选择时影响 CPSR。
Rd 目标寄存器。用于存放运算的结果。
Rn 第 1 个操作数寄存器。用于存放参与运算的操作数 1。
operand2 第 2 个操作数。用于指定参与运算的操作数 2。
【例 3-1】
MOV R0,R1 ;将 R1 中的值送入 R0
SUBS R0, R1, R2 ;将 R1 中值减去 R2 的值,结果保存到 R0,并影响 CPSR。
LDR R0, [R1, #0x0C] ;将 R1+0x0C 所指向的存储器单元内容加载到 R0 中。
ARM 处理器支持 16 种条件码,分别对应了 CPSR 寄存器标志位(N、Z、C、V)的 16
个组合状态值,处理器根据 CPSR 中标志位 N、Z、C 和 V 的值来确定指令是执行还是跳过。
表 3-2 给出了这些条件码助记符及其对应的状态标志值。ARM 指令使用条件码助记符来指
定本指令的执行条件。其中条件(AL) 是缺省条件,可以省略。如果指令不含有条件码助记
符时,就默认是该条件。
ARM 指令具有条件执行的特点,提高了程序中条件语言的效率,如【例 3-2】
3.1.3 指令的条件域
ARM 指令集中每条指令都可以条件执行,这也是 ARM 指令系统的特点之一。所谓的
ARM 指令‘条件执行’是指在指令码中含有本条指令的执行条件,当 CPSR 中的条件码标
志满足时,处理器执行本条指令,否则本条指令等价于空操作。使用指令条件码可实现高效
的逻辑操作,提高代码执行效率。ARM 处理器支持 16 种条件码,如表 3-2 所示。
3.1.4 第 2 个操作数(operand2)的三种形式
- #immed_8r——常数表达式;
- Rm——寄存器方式;
- Rm,shift——寄存器移位方式。
1.常数表达方式
#immed_8r 是常数表达式,该常数必修对应 8 位位图,即常数是由一个 8 位的常数循环
左移偶数位得到。例如 0x3FC00(0xFF<<10)、0x168(0x5A<<2)、0x350000(0x35<<16)、
0xE0000007(0x7E<<28)是合法常数;而 0x3F2、286、0x10010、0x50000020 是非法常数。
【例 3-2】
MOV R2,#100 ;R2←100
AND R1,R2,#0x3F00 ;R2 与 0x3F00,结果保存到 R1 中
LDR R0,[R1],# -8 ;将 R1 指向的存储器单元内容加载到 R0 中,随后 R1←R1-8
2.寄存器方式
Rm 指寄存器方式,在寄存器方式下操作数即为寄存器中的数值。
【例 3-3】
SUB R0,R1,R2 ;R0=R1-R2
MOV PC,R0 ;PC=R0,ARM 处理器将跳转到 R0 指定地址处执行
LDR R0,[R1],-R2 ;将 R1 指向的存储器单元内容加载到 R0,修改 R1=R1-R2
3.寄存器移位方式
Rm,shift 表示使用寄存器的移位结果作为操作数,但 Rm 值保持不变。移位方法如图
3.2 所示:
LSL # n ;逻辑左移 n 位(1≤n≤31)
LSR # n ;逻辑右移 n 位(1≤n≤31)
ASR # n ;算术右移 n 位(1≤n≤31)
ROR # n ;循环右移 n 位(1≤n≤31)
RRX ;带扩展的循环右移,操作数右移一位,高位有 C 标志填充。
Type Rs ; type 为 ASR、LSL、LSR 和 ROR 中的一种;Rs 偏移量寄存器,
;低 8 位有效。通常使用通用寄存器用作 Rs
【例 3-4】
ADD R0,R1,R1,LSL #3 ;R0=R1+(R1<<3)。
SUB R0,R1,R2,LSR R3 ;R0 = R1-(R2 >>(R3))。
MOV R0,R1,RRX ;将 R1 带扩展的循环右移 1 位,存入 R0 中
3.2. ARM 指令的寻址方式
寻址方式是处理器根据指令中给出的地址信息来寻找物理地址的方法,ARM 处理器有
8 种基本寻址方式。
(1) 立即寻址
立即寻址也叫立即数寻址,立即寻址指令中的地址码部分就是操作数本身,即操作数包
含在指令之中,取出指令也就取出了可以立即使用的操作数。
【例 3-5】
MOV R0,#75 ;将立即数 75 送入 R0。
SUB R1,R0,#0x5600 ;R0 的值减立即数 0x5600,然后将结果送回 R1。
前缀“#”号表示立即数,“0x”表示 16 进制数值。
(2)寄存器寻址
寄存器寻址就是将寄存器中的数值作为操作数,指令中的地址码指出的是寄存器编号,
指令执行时直接取出寄存器值进行操作。
【例 3-6】
MOV R0,R1 ; R0←R1
SUB R0,R1,R2 ;R0←R1-R0
(3)寄存器移位寻址
寄存器移位寻址是ARM指令集特有的寻址方式,当第二个操作数是寄存器偏移方式时,
可以选择进行移位操作。
【例 3-7】
MOV R0,R1,LSL #3 ;R1 的值逻辑左移 3 位,结果放入 R0
;即是 R0=R1×8
MOV R0,R1,ROR R2 ;R1 的值循环右移 R2 位,然后放入 R0
AND R0,R1,R2,LSL R3 ;R2 的值逻辑左移 R3 位,再和 R1 的值相“与”,
;结果放入 R0
(4)寄存器间接寻址
寄存器间接寻址就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储器
中,即寄存器用作操作数的地址指针。
【例 3-8】
LDR R0,[R1] ;将 R1 指向的存储单元中的数据,读取后保存到 R0 中
STR R0,[R1] ;将 R0 中的数据保存到 R1 指向的存储单元中
(5)基址变址寻址
基址变址寻址就是将寄存器(一般称为基址寄存器)中的内容与指令中给出的地址偏移
量相加,形成操作数的有效地址。基址变址寻址用于访问基址附近的存储单元,常用于查表、
数组操作、功能部件寄存器访问等。寄存器间接寻址是偏移量为0的基址变址寻址。
基址变址寻址分为前变址法和后变址法
① 前变址法(也叫前索引偏移):基地址寄存器中的值和地址偏移量先作加减运算,生
成的操作数作为内存访问的地址。
② 后变址法(也叫后索引偏移):将基地址寄存器中的值直接作为内存访问的地址进行
操作,内存访问完毕后基地址寄存器中的值和地址偏移量作加减运算,并更新基地址寄
存器内容。
【例3-9】
LDR R0,[R1,#6] ;R0←[R1+6]。
将寄存器R1的内容加上6形成操作数的有效地址,然后将读取该有效地址中的数据保存
到寄存器R0中。
LDR R0,[R1,#6]! ;R0←[R1+6],R1←R1+6。
将寄存器R1的内容加上6形成操作数的有效地址,并保存到R1中,然后将读取该有效地
址中的数据保存到寄存器R0中。
LDR R0,[R1],#6 ;R0←[R1],R1←R1+6。
以寄存器R1的内容为操作数的有效地址,从该地址中取得操作数存入寄存器R0中,然
后将R1的内容加6。
LDR R0,[R1,R2] ;R0←[R1+R2]。
将寄存器R1的内容加上寄存器R2的内容形成操作数的有效地址,从该地址中取得操作
数存入寄存器R0中。
例 3-9 中除了第三条指令为后索引偏移之外,其他为前索引偏移,其中“!”表示带返
回值的前索引偏移。
补充:表5-6
符号“!”表示指令完成数据传送后更新基址寄存器的值。
(6)相对寻址
相对寻址是基址寻址的一种变通。由程序计数器 PC 作为基地址寄存器,指令中的地址
码字段作为偏移量,两者相加后得到的地址即为操作数的有效地址。
【例 3-10】
Start
MOV R0, #0
MOV R1, #3
MOV R2, #2
BL arithfunc ;转移到arithfunc,是相对寻址
... ...
arithfunc
CMP R0, #num
MOVHS PC, LR ;返回
... ..
相对寻址中偏移量及有效地址的计算如下图3.3所示。
(7)多寄存器寻址
多寄存器寻址是指一次可以传送多个寄存器的值,允许一条指令传送 16 个寄存器的任
何子集或所有 16 个寄存器。
【例 3-11】
LDMIA R1!,{R2-R5,R12} ;R2←[R1],R1←R1+4
;R3←[R1],R1←R1+4
;R4←[R1],R1←R1+4
;R5←[R1],R1←R1+4
;R12←[R1],R1←R1+4
STMIA R0,{R2-R5, R12} ;[R0]←R2
;[R0+4]←R3
;[R0+8]←R4
;[R0+12]←R5
;[R0+16]←R12
指令中IA表示先传送数据,之后地址加4,第一条语句是将R1所指向的存储器区域中的
内容依次加载到R2~R7、R12(每传送一个寄存器值后,R1的值自动加4并保存)。第二条语
句是将R2~R7、R12中的值依次保存到R0所指向的存储器区域中(每传送一个寄存器值后,
R0的值自动加4,但不保存)
使用多寄存器寻址指令时,寄存器子集的顺序应按由小到大的顺序排列,连续的寄存器
可用“-”连接,否则用“,”分隔书写。
补充:表5-7
(8)堆栈寻址
堆栈是一个按特定顺序进行存取的存储区,操作顺序为“先进后出” ,堆栈寻址是隐含
的,它使用一个专门的寄存器(堆栈指针)指向一块存储区域(堆栈),指针所指向的存储单元
是堆栈的栈顶。堆栈按照生长方向可分为两种如图3.4所示:
向上生长:向高地址方向生长,称为递增堆栈
向下生长:向低地址方向生长,称为递减堆栈
从堆栈指针指向的栈顶位置不同,又分为满堆栈和空堆栈,如图3.5所示。
满堆栈:堆栈指针SP指向最后压入的堆栈的有效数据项,
空堆栈:堆栈指针SP指向下一个待压入数据的空位置,
根据上述堆栈生长方式和堆栈指针位置的不同,可以组合出四种类型的堆栈方式:
① 满递增堆栈:堆栈向上增长,堆栈指针SP指向含有效数据项的最高地址。指令如
LDMFA、STMFA等;
② 空递增堆栈:堆栈向上增长,堆栈指针SP指向堆栈上的第一个空位置。指令如
LDMEA、STMEA等;
③ 满递减堆栈:堆栈向下增长,堆栈指针SP指向含有效数据项的最低地址。指令如
LDMFD、STMFD等;
④ 空递减堆栈:堆栈向下增长,堆栈指针SP指向堆栈下的第一个空位置。指令如
LDMED、STMED等。
解释采自:https://www.jianshu.com/p/aa4695b6bc26
LD : load 加载,出栈操作
ST : store 存储,入栈操作
M : multi 多次
F:full 满栈,SP指向最后一个数据
E:empty 空栈,SP指向与最后一个数据相邻的下一个可写入存储单元
D:descending 递减,代表栈的增长方向
A:ascending 递增,代表栈的增长方向
【例 3-12】
STMFD SP!,{R1-R7,LR} ;将 R1~R7,LR 入栈,满递减堆栈
LDMFD SP!,{R1-R7,LR} ;数据出栈,放入 R1~R7,LR 寄存器,
;满递减堆栈
补充:表5-8
3.3. ARM 指令集介绍
3.3.1 数据处理指令
ARM 指令集的数据处理指令可分为 4 类:数据传送指令、算术运算指令、逻辑运算指
令和比较指令。
其汇编指令语法格式如下:
< opcode>{< cond>}{S} < Rd>,< Rn>,< operand2>
数据处理指令的操作及功能如表 3-2 所示。
3.3.2 乘法指令
ARM 乘法指令完成 2 个 32 位数的乘法,按照保存结果的数据长度可以分为两类:一类
为 32 位的乘法指令,即乘法操作的结果为 32 位;另一类为 64 位的乘法指令,即乘法操作
的结果为 64 位。乘法指令如表 3-3 所示。
3.3.3 分支指令
分支指令用于实现程序流程的跳转,在 ARM 程序中有两种方法可以实现程序流程的跳
转。
① 直接向程序计数器 PC 写入跳转地址值。
通过向程序计数器 PC 写入跳转地址值,可以实现在 4GB 的地址空间中的任意跳转,
在跳转之前结合使用 MOV LR,PC 等类似指令,能够保存程序的返回地址值,从而实现
在 4GB 连续地址空间的子程序调用。
② 使用专门的分支指令。
下面介绍三种分支指令如表 3-4 所示:
- 分支指令 B;
- 带连接的分支指令 BL;
- 带状态切换的分支指令 BX。
3.3.4 程序状态寄存器访问指令
ARM 处理器支持程序状态寄存器 PSR 访问指令,用来实现通用寄存器与程序状态寄存
器之间传送数据,共有两条:读程序状态寄存器指令 MRS 和写程序状态寄存器指令 MSR。
这类指令可以用来修改 CPSR,采用“读取-修改-写回”操作顺序实现。但是对于 CPSR 中
的 T 控制位不可以采用这种方式修改,因为 T 位的变化涉及处理器状态的切换,只能通过
BX 指令完成程序状态切换。
① MRS 读状态寄存器指令
MRS 指令格式: MRS{cond} Rd, CPSR
MRS{cond} Rd, SPSR
其中: Rd 为目标寄存器,Rd 不允许为 R15。
MRS 指令将 CPSR 或 SPSR 中的内容装入到一个通用寄存器中。在 ARM 处理器中,只
有 MRS 指令可以对状态寄存器 CPSR 和 SPSR 进行读操作。通过读 CPSR 可以了解当前处
理器的工作状态。读 SPSR 寄存器可以了解到进入异常前的处理器状态。
【例 3-38】
MRS R0, CPSR ; 将 CPSR 状态寄存器值读取到 R0 中
MRS R2, SPSR ; 将 SPSR 状态寄存器值读取到 R2 中
② MSR 写状态寄存器指令
指令格式:MSR{cond} PSR_fields, #immed_8r
MSR{cond} PSR_fields, Rm
其中: immed_8r:要传送到状态寄存器指定域的 8bit 立即数,。
Rm :要传送到状态寄存器指定域的源寄存器数。
PSR :指 CPSR 或 SPSR 寄存器。
Fields:指定传送的区域,分别对应 PSR 的 4 个字节片段。fields 可以是以下
的一种或多种(字母必须为小写):
- c 控制域字节(psr[7…0]);
- x 扩展域字节(psr[15…8]);
- s 状态域字节(psr[23…16]);
- f 标志域字节(psr[31…24])。
各个域在 CPRS 寄存器中的位置如错误!未找到引用源。所示。
MSR 指令将一个立即常数装载到 CPSR 或 SPSR 指定的位域中,或者将一个通用寄存
器中的内容装载到 CPSR 或者 SPSR 中。在 ARM 处理器中,只有 MSR 指令可以对状态寄
存器 CPSR 和 SPSR 进行写操作。
【例 3-39】
MSR CPSR_c, #0xD3 ; CPSR[7…0]=0xD3,即切换到管理模式
MSR CPSR_cxsf, R3 ; CPSR=R3
注意:MRS 指令读取 CPSR,可用来判断 ALU 的状态标志,或 IRQ、FIQ 中断是否允
许等。在异常处理程序中,读 SPSR 可知道进入异常前的处理器状态等。MRS 与 MSR 配合
使用,实现 CPSR 或 SPSR 寄存器的“读-修改-写”操作,可用来进行处理器模式切换、
允许/禁止 IRQ/FIQ 中断等设置。
【例 3-40】使能 IRQ 中断
ENABLE_IRQ
MRS R0, CPSR
BIC R0, R0, #0x80 ; 清除 CPSR 的 I 位,允许处理器 IRQ 中断
MSR CPSR_c, R0
MOV PC, LR
【例 3-41】禁止 IRQ 中断
DISABLE_IRQ
MRS R0, CPSR
ORR R0, R0, #0x80 ; 将 CPSR 的 I 位置‘1’,屏蔽处理器的 IRQ 中断
MSR CPSR_c, R0
MOV PC, LR
【例 3-42】地址指针初始化
INITSTACK
; 设置管理模式堆栈指针
MRS R0 , CPSR ;读 CPSR 到 R0
BIC R0 , R0,#0x1F ;R0 的低 5 位清零
ORR R0 , R0,#0x13 ;0x13 是管理模式编码
MSR CPSR_c, R0 ; 切换处理器工作模式到“管理模式”
LDR SP, StackSvc ; 开辟‘管理模式’下的堆栈区
; 设置 IRQ 中断模式堆栈指针
MRS R0 , CPSR ;读 CPSR 到 R0
BIC R0 , R0,#0x1F ;R0 的低 5 位清零
ORR R0 , R0,#0x12 ;0x12 是 IRQ 模式码
MSR CPSR_c, R0 ; 切换处理器工作模式到‘irq 模式’
LDR SP, StackIrq ; 开辟‘irq 模式’下的堆栈区
…
小tip:
如何记忆MRS和MSR
记住:
M:Move output<-input 移动
R:regs 一般寄存器
S:status regs 状态寄存器
3.3.5 ARM 软中断指令
ARM 处理器支持异常产生指令 SWI,用于引起 SWI 异常,使得处理器模式从用户模式
切换到管理模式,同时程序跳转到 SWI 异常向量入口 0x08 地址处开始执行指令。ARM 处
理器通过这种机制实现用户模式进入到特权模式,实现操作系统中特权模式的程序调用,也
就是使用户程序调用操作系统的系统程序成为可能。SWI 指令不影响条件码标志。
SWI 指令的编码格式如下:
【例 3-43】
MOV R0,#34 ;设置子功能号为 34
SWI 0x123456 ;调用 0x123456 号软中断
也可以将指令中的 24 位立即数被忽略,用户请求的服务类型由寄存器 R0 的值决定,
参数通过其它的通用寄存器传递。
【例 3-44】
MOV R0,# 0x123456 ;调用 12 号软中断
MOV R1,#34 ;设置子功能号为 34
SWI 0
在用户模式下,有一些资源不能访问,如确需访问时,可使用 SWI 指令(也称为软件
中断指令)先切换处理器模式到‘管理模式’,在管理模式下完成受限资源的访问,之后再
返回用户模式,实现了系统软件的管态模式。
在 SWI 异常中断处理程序中,取出 SWI 指令中立即数的步骤为:
① 首先确定引起软中断的 SWI 指令是 ARM 指令还是 Thumb 指令,这可通过对 SPSR
访问得到;
② 然后取得该 SWI 指令的地址,这可通过访问 LR 寄存器得到;
③ 接着读出该 SWI 指令,分解出立即数。
【例 3-45】
SWI_Handler
STMFD SP!,{R0-R3,R12,LR} ;现场保护
MRS R0,SPSR ;读取 SPSR
STMFD SP!,{R0} ;保存 SPSR
TST R0,#0x20 ;测试 T 标志位
LDRNEH R0, [LR,#-2] ;若是 Thumb 指令,读取指令码(16 位)
BICNE R0,R0,#0xFF00 ;取得 Thumb 指令的 8 位立即数(低 8 位)
LDREQ R0,[LR,#-4] ;若是 ARM 指令,读取指令码(32 位)
BICEQ R0,R0,#0xFF000000 ;取得 ARM 指令的 24 位立即数(低 24 位)
... …
LDMFD SP!,{R0-R3, R12,PC}^ ;SWI 异常中断返回,添加“^”符号表示
;同时将 SPSR 内容拷贝到 CPSR 中。
3.3.6 ARM 存储器访问指令
ARM7 处理器是典型的 RISC 处理器,对存储器访问只能使用加载和存储指令实现。存
储器的地址空间和 I/O 地址空间实行统一编址,除对 RAM 操作以外,对外围 IO、程序数据
的访问均要通过加载/存储指令进行。
ARM 存储器访问指令主要包括 3 种基本的加载/存储指令:即单寄存器加载/存储指令、
多寄存器加载/存储指令和单寄存器交换指令 SWP(Single register sWaP),可实现字、无符
号半字/有符号半字、无符号字节/有符号字节等类型数据的加载/存储操作。ARM 存储器访
问指令见表 3-6。
1. 单寄存器加载/存储指令
从寻址方式中地址计算方法来划分,加载/存储指令有 4 种格式:
① 零偏移。当偏移量为 0 时,即为零偏移。
② 前索引偏移。在数据传送之前,先通过基地址和偏移量的值计算有效地址,将有效
地址作为传送数据的存储地址。若使用后缀“!”,则将有效地址写回到基址寄存器 Rn 中,
且 Rn 不允许为 R15;否则,不修改基址寄存器的值。
③程序相对偏移。将基址寄存器默认为 PC。并且在语句中省略,只保留偏移量(通常
直接使用语句标号指定)。不能使用后缀“!”。
④ 后索引偏移。基址寄存器的值直接用作传送数据的存储地址。在数据传送后,将基
址寄存器 Rn 与偏移量求和,并将结果写回到 Rn 中,Rn 不允许是 R15。
注意:必须保证字数据操作的地址是字对齐存储。
【例 3-49】
LDRT R0,[R1] ;零偏移,以用户模式。
LDR Rd,[Rn,Rm]! ;前索引偏移,要求将 Rn 与 Rm 之和写回到 Rn 中。
STR Rd,[Rn,#-0x04] ;前索引偏移,要求(Rn-0x04)不写回 Rn。
STR Rd,[Rn],#0x04 ; 后索引偏移,要求 Rn= Rn+0x04。
LDR Rd,[Rn],Rm ;后索引偏移,要求 Rn= Rn+Rn。
LDR Rd,label ;将标号 label 地址中存放的数据加载到 Rd 中。
2. 多寄存器加载/存储指令
多寄存器加载/存储指令可以实现在一组寄存器和一块连续的内存单元之间传输数据。
LDM 为加载多个寄存器;STM 为存储多个寄存器。
I:increase v.增加
D:decrease v.减少
A:after prep.之后
B:before prep.之前
区别:只有!,使得指令完成数据传送后更新基址寄存器R0的值。
说明 //地址±1就是R0±4
IA:传送后增加//后缀地址++;M=[R0++]
IB:传送前增加//前缀地址++;M=[++R0]
DA:传送后减少//后缀地址--;M=[R0--]
IB:传送前减少//前缀地址--;M=[--R0]
3. 堆栈操作指令
4. SWP 寄存器和存储器交换指令
3.3.7 ARM 协处理器操作指令
3.3.8 ARM 伪指令
1. LDR 大范围的地址或立即数的读取
【例3-56】
2. ADRL 中等范围的地址读取伪指令
3. ADR 小范围的地址读取伪指令
4. NOP 空操作伪指令
NOP 伪指令在汇编时将会被代替成 ARM 中的空操作,比如可能为“MOV R0, R0”指
令等。NOP 可用于延时操作。
指令格式:NOP
Delay
NOP ;空操作
NOP
NOP
SUBS R0,R0,#1 ;循环次数减一
BNE Delay ;如果循环未结束,跳转 Delay 继续
MOV PC,LR ;子程序返回
3.4. Thumb 指令集
在ARM体系结构中,ARM指令是32位的,具有很高的执行效率。但是对于嵌入式设备
而言,其存储空间极其有限,由于每条ARM指令占用4个字节,对存储空间的要求较高。为
了压缩代码的存储,增加代码存储密度,ARM公司设计了16位的Thumb指令集。 Thumb指
令集可以看作是ARM指令压缩形式的子集,在保留32位代码优势的同时,大大地节省了系
统的存储空间。但是Thumb指令体系不完整,只支持通用功能。必要时仍需要使用ARM指
令,如进入异常模式时。
所有的Thumb指令都有对应的ARM指令,而且Thumb的编程模型也对应于ARM编程模
型,在应用程序的编写过程中,ARM汇编语言提供了两条伪操作CODE32和CODE16用来分
别指示ARM程序段和Thumb程序段,只要遵循一定调用规则,Thumb程序和ARM程序就可
以相互调用。处理器为了区分ARM程序运行状态和Thumb程序运行状态,在程序状态寄存
器中设置了一个T标志位,用来标志ARM处理器运行的指令类型,当处理器运行ARM程序
段时,T标志位为0,当处理器运行Thumb程序段时,T标志位为1,T标志位的设置可以通过
状态切换分支BX指令实现。
在应用过程中,ARM指令集和Thumb指令集各有其优点,在一般情况下ARM指令和
Thumb指令的时间效率和空间效率关系如下:
① Thumb代码所需的存储空间约为ARM代码的60%~70%。
② Thumb代码使用的指令数比ARM代码多约30%~40%。
③ 在32位的存储器中,ARM代码比Thumb代码快约40%。
④ 在16位的存储器中,Thumb代码比ARM代码快约40%~50%。
⑤ 与ARM代码相比,使用Thumb代码,存储器的功耗会降低约30%。
显然,在编程时,可根据任务需求和存储器资源进行合理的选择应用那种类型的指令,
如对系统的性能有较高要求,应该使用ARM指令集;如对系统的成本及功耗有较高要求,则
应该使用Thumb指令集。本节对Thumb指令集做简单介绍。
Thumb指令集较ARM指令集有如下限制:
① 只有B指令可以条件执行,其它指令都不能条件执行;
② 分支指令的跳转范围有更多限制;
③ 数据处理指令的操作结果必须放入操作数中的一个;
④ 单寄存器访问指令,只能操作R0~R7;
⑤ LDM和STM指令可以对R0~R7的任何子集进行操作;
最后
2023-7-3 18:04:30
祝大家逢考必过
点赞收藏关注哦