ARM 嵌入式微处理器指令集(上)
教材:嵌入式系统及应用,罗蕾、李允、陈丽蓉等,电子工业出版社
目录:
ARM 嵌入式微处理器指令集
ARM 处理器实现的指令集
- 32 位的 ARM 指令集和 16 位的 Thumb 指令集
- ARM 处理器允许在 ARM 状态和 Thumb 状态之间进行切换和互操作,保证用户在运算性能和代码密度之间的选择的灵活性
- 采用 16 位的 Thumb 指令集优势在于更高的代码密度和降低功耗
- Thumb 指令集的代码一般是由编译器生成的而不是手动编写出来的
ARM 指令集的特点
- 所有 ARM 指令都是 32 位定长的,内存中地址以 4 字节边界对齐,故 ARM 指令的有效地址最后两位总是 00
- 加载 - 存储架构。除了专门的加载 - 存储类型的指令可以访问内存外,其余指令使用处理器内部寄存器的数据和立即数作为操作数
- 提供一次加载和存储多个寄存器的指令:LDM 和 STM。这样,发生过程调用和中断处理时,只用一条指令即可把多个寄存器的内容保存到内存堆栈中
- CPU 内核硬件中提供了桶形移位器,移位操作可以内嵌在其他指令中,即一条指令可在一个指令周期完成一个移位操作和一个 ALU 操作
- 所有 ARM 指令都可以条件执行,其指令高四位是条件指示位,根据 CPSR 寄存器中的N、Z、C、V 决定该指令是否执行
Thumb 指令集的约束
- 不使用条件执行,标志总是根据指令结果设置
- 源寄存器和目标寄存器相同
- 不使用 R8~R12 寄存器,只用低端寄存器
- 指令中出现的常量有大小的限制
- 不在指令中使用内嵌的桶形移位器
ARM v4T 架构指令体系
条件执行和标志位
- 通过在指令后加上合适的条件标志位,ARM 指令可以条件执行
- 减少了分支指令数目,增强了指令的代码密度和性能
- 比较指令(CMP)默认影响标志位
- 数据处理指令默认不会影响条件标志位,但是可在指令后加“S”(或其它条件位的)后缀,以实现标志位的置位
- 条件执行的例子
- 指令条件码
数据处理指令
- 算术运算: ADD ADC SUB SBC RSB RSC
- 逻辑运算: AND ORR EOR BIC
- 比较运算: CMP CMN TST TEQ
数据传送: MOV MVN
-
通用语法:
<Operation>{<cond>}{S} Rd, Rn, Operand2
- 第二个操作数可以为一个寄存器或者一个立即数,对应最低的 12 个有效位
- 比较指令和数据传送指令不指定 Rn
-
第二个操作数可以通过桶型移位器传输到 ALU
- 第二个操作数采用寄存器方式
可附加移位操作,移位的值可为 5 位的无符号整数(0~31),或者是其他寄存器的最低字节 - 第二个操作数是立即数
需满足是 0~255 的 8 位立即数或者是通过一个 8 位的立即数循环右移偶数位得到的数(4 位的移位数乘以 2 组成了步长,范围在0-30 的移位值 )
- 第二个操作数采用寄存器方式
- 加载 32 位常数
LDR rd, =const
,推荐用这种方式将常数加载到寄存器
乘法和除法
-
产生 32 位结果的乘法
MUL r0, r1, r2 ; r0 = r1 * r2 MLA r0, r1, r2, r3 ; r0 = (r1 * r2) + r3
-
产生 64 位结果的乘法(分无符号乘和有符号乘)
[U|S]MULL r4, r5, r2, r3 ; r5:r4 = r2 * r3 [U|S]MLAL r4, r5, r2, r3 ; r5:r4 = (r2 * r3) + r5:r4
大多数的 ARM 核不提供整数除法指令,除法操作由 C 的库函数例程或者移位操作实现
分支指令
实现程序的跳转,格式:
B{L}{<cond>} label
(子函数调用时加上 {L})label
在指令编码中是一个 24 位的地址,在执行时它被左移两位 ( ARM 指令是字对齐的),产生一个 26 位的偏移地址,跳转范围在当前指令地址 -32MB ~ 32MB 中执行该指令会引起流水线的清空
子程序调用
- 需要保存返回地址并且跳转到子程序的首地址
- 这些步骤可以由一条指令
BL
完成 - 返回地址被保存在链接寄存器 (LR寄存器/r14)中
- 分支跳转到 +/- 32MB 范围内的任何地址
-
子程序在执行的最后重新加载 LR 寄存器的内容至 PC 寄存器
单寄存器的数据传输
用于存储器和内核寄存器之间的数据传输
指令 功能 LDR STR 加载/存储字 LDRB STRB 加载/存储字节 LDRH STRH 加载/存储半字 LDRSB 加载有符号的字节 LDRSH 加载有符号的半字 语法
LDR{<cond>}{<size>} Rd, <address>
STR{<cond>}{<size>} Rd, <address>
-
指令中的地址通过一个基址寄存器和一个偏移量来确定
- 对于字和无符号的字节访问, 偏移量可以为
- 无符号的 12 位立即数(0 ~ 4095 字节),
LDR r0, [r1, #8]
- 一个寄存器,可附加的对其进行移位,
LDR r0, [r1, r2, LSL#2]
- 对于半字和有符号的字节访问, 偏移量可以为
- 一个 8 位的立即数 (0 - 255 bytes)
- 一个寄存器 (不可以被移位)
前序寻址和后序寻址
后序寻址的方式下基址寄存器的质自动更新,前序寻址不会更新,除非加上'!'
-
通过 LDR 指令实现跳转
- 直接将任意的 32 位地址加载到 PC 中,实现 4GB 地址空间内的跳转
LDR pc, =label ; 将标号的地址加载到PC中
批量加载/存储
语法:
<LDMxx|STMxx>{<cond>}<addressing_mode> Rb{!}, <register list>
指令 地址模式 堆栈工作方式 LDMIA/STMIA 访存后地址增加(Increment After, IA) 空递增 LDMIB / STMIB 访存前地址增加(Increment Before, IB) 满递增 LDMDA / STMDA 访存后地址递减(Decrement After, DA) 空递减 LDMDB / STMDB 访存前地址递减(Decrement Before, DB) 满递减 区别
-
批量加载/存储指令常常用来实现堆栈的操作
- STMFD:push 操作,FD 意为满递减(Full Decrement),实际对应 STMDB 指令
- LDMFD:pop 操作,实际对应 LDMIA 指令
- 寄存器在压栈时的顺序始终是最低编号寄存器的内容压入最低地址的堆栈空间,被指定的寄存器顺序是无效的
交换指令
- 内存和寄存器之间传送一个字节或字的原子操作(不可被打断),先读取内存后写内存
- 操作期间阻止其他任何指令对该存储单元的读/写,可用于实现信号量和互斥操作
-
SWP{<cond>}{B} Rd, Rm, [Rn]
- Rd 是目的寄存器,从存储器中读到的值存放于此寄存器中
- Rm 寄存器是操作数,会将此寄存器中的值存放于存储单元中
- [Rn] 是寄存器间接寻址,Rn 保存的是某个存储单元的地址
- 不能由 ARM 编译器编译高级语言程序得到,只能手工编写汇编指令实现
软中断指令
- 引起了一个异常自陷, 跳转到软中断异常向量
- 软中断处理例程检查软中断号以决定如何处理该号中断
- 通过软中断这种机制,操作系统可以实现一个特权操作集合,它们可被用户模式下的应用代码调用
- 语法:
SWI{<cond>} <SWI number>
程序状态寄存器访问指令
MRS / MSR 指令用于在 CPSR / SPSR 寄存器与通用寄存器之间传输数据
-
通过写CPSR寄存器,可以开关中断、改变处理器模式
使用一个读/修改/写的操作序列
MRS r0,CPSR ; 将 CPSR 的内容读至 r0 BIC r0,r0,#0x80 ; 将第7位清零以允许IRQ中断 MSR CPSR_c,r0 ; 将修改后的值仅写入‘c’字节
在用户模式下, 所有的位都可以被读出来,但是仅有条件标志位(F)可以被改变
协处理器指令
- ARM 体系支持16个协处理器
- 每个协处理器的指令集都占据了 ARM 指令集的固定部分
- 如果系统中没有某个协处理器, 那么就会触发未定义指令异常
协处理器数据操作指令
- CDP : 初始化协处理器的数据处理操作
协处理器寄存器与 ARM 处理器寄存器数据传输指令
- MRC : 协处理器寄存器到ARM 处理器寄存器的数据传输指令
- MCR : ARM 处理器寄存器到协处理器寄存器的数据传输指令
协处理器寄存器和内存的数据传输指令
- LDC : 协处理器数据加载指令
- STC : 协处理器数据存储指令
上一篇: AndroidStudio之百度地图——集成SDK
下一篇: argparse基本用法(笔记)