《ARM体系结构与编程》学习笔记
第1章 ARM概述及编程模型
这一章讲了ARM的一些基本概念,和ARM的编程模型.
编程模型:运行模式,寄存器,异常中断,存储系统
一.概述(略)
- 了解ARM体系结构的版本
- 了解ARM体系的变种(Thumb指令集,长乘法指令集…)
- ARM/Thumb体系版本命名
- ARM处理器系列(ARM7,ARM9…)
二.编程模型(以下)
1.ARM处理器的运行模式
ARM处理器的7种运行模式
- 用户模式(User,usr):正常程序执行的模式
- 快速中断模式(FIQ,fiq):用于高速数据传输和通道处理
- 外部中断模式(IRQ,irg):用于通常的中断处理
- 特权模式( Supervisor,sve):供操作系统使用的一种保护模式
- 数据访问中止模式( Abort,abt):用于虚拟存储及存储保护
- 未定义指令中止模式( Undefined,und):用于支持通过软件仿真硬件的协处理器
- 系统模式( Systen,sys):用于运行特权级的操作系统任务
除了用户模式外,其他六种都是特权模式。特权模式中除了系统模式外,其他五种又称为异常模式。
大多数用户程序运行在用户模式,无法访问受操作系统保护的系统资源,需要通过产生异常处理;来进入相应的异常模式。
系统模式无法通过异常模式进入,主要供操作系统使用。
2.ARM寄存器
ARM处理器共有37个寄存器。其中包括:
- 31个通用寄存器,包括程序计数器(PC)在内。这些寄存器都是32位寄存器。
- 6个状态寄存器。这些寄存器都是32位寄存器,但目前只使用了其中12位。
ARM处理器共有7种不同的处理器模式,在每一种处理器模式中有一组相应的寄存器组。任意时刻(也就是任意的处理器模式下),可见的寄存器包括15个通用寄存器(R0~R14)、一个或两个状态寄存器及程序计数器(PC)。在所有的寄存器中,有些是各模式共用的同一个物理寄存器:有一些寄存器是各模式自己拥有的独立的物理寄存器。
下图列出了各种处理器模式下可见的寄存器情况。
通用寄存器
通用寄存器可以分为下面3类:
- 未备份寄存器( Unbanked Registers ),包括RO~R7
- 备份寄存器( Banked Registers),包括R8~R|4
- 程序计数器PC,即R15
- 未备份寄存器,在各个处理器模式下用的都是同一个寄存器。
- 备份寄存器在不同的处理器模式下用的寄存器不同。
- 比如:R13常用作栈指针,不同模式下,我们标记为R13_
,mode可以是 usr
、sve
、abt
、und
、iq
及fiq
。 - R14被称为连接寄存器:一般保存子程序的返回地址,或异常模式要返回的地址。
- 比如:R13常用作栈指针,不同模式下,我们标记为R13_
- 程序寄存器R15(PC):当前指令地址值加8个字节,避免用
STR/STM
保存R15的值(可能会保存加12的值),和芯片的实现方式有关
程序状态寄存器
CPSR
(当前程序状态寄存器)可以在任何处理器模式下被访问。它包含了条件标志位、中断禁止位、当前处理器模式标志以及其他的一些控制和状态位。每一种处理器模式下都有一个专用的物理状态寄存器,称为SPSR
(备份程序状态寄存器).当特定的异常中断发生时,这个寄存器用于存放当前程序状态寄存器的内容。在异常中断程序退出时,可以用SPSR
中保存的值来恢复CPSR
.
由于用户模式和系统模式不是异常中断模式,所以它们没有SPSR
.当在用户模式或
系统模式中访问SPSR时,将会产生不可预知的结果。
CPSR的格式如下图所示。SPSR格式与CPSR格式相同。
1.条件标志位
N( Negative)、Z(zero)、c(Cary)及 V(oVerflow)统称为条件标志位。大部分的ARM指令可以根据CPSR中的这些条件标志位来选择性地执行。各条件标志位的具体含义如下图所示。
以下指令会影响CPSR中的条件标志位
- 比较指令,如CMP、CMN、TEQ及TST等。
- 当一些算术运算指令和逻辑指令的目标寄存器不是R15时,这些指令会影响CPSR中的条件标志位
- MSR指令可以向 CPSR/SPSR中写入新值。
- MRC指令将R5作为目标寄存器时,可以把协处理器产生的条件标志位的值传送到ARM处理器。
- 一些LDM指令的变种指令可以将SPSR的值复制到CPSR中,这种操作主要用于从异常中断程序中返回。
- 一些带“位设置”的算术和逻辑指令的变种指令,也可以将SPSR的值复制到CPSR中,这种操作主要用于从异常中断程序中返回。
2.Q标志位
在 ARMyS的E系列处理器中,CPSR的bit[27]称为Q标志位,主要用于指示增强的DSP指令是否发生了溢出。同样的SPSR中的bi[27也称为Q标志位,用于在异常中断发生时保存和恢复CPSR中的Q标志位。
在ARMv5以前的版本及 ARMV5的非E系列的处理器中,Q标志位没有被定义CPSR的bit[27]属于DNM(RAZ)
3.CPSR中的控制位
CPSR的低8位1、F、T及M[40统称为控制位。当异常中断发生时,这些位发生变化。在特权级的处理器模式下,软件可以修改这些控制位。
- 中断禁止位
- ①当F=1时禁止IRQ中断。
- ②当F=1时禁止FlQ中断。
- T控制位
- T控制位用于控制指令执行的状态,即说明本指令是ARM指令,还是 Thumb指令对与不同版本的ARM处理器,T控制位的含义不同。
- 对于ARM3以及更低的版本和ARMv4的非T系列版本的处理器,没有ARM状态和 Thumb状态切换,T控制位应为0.
- 对于ARMv4以及更高的版本的T系列的ARM处理器,T控制位的含义如下。
- ①T=0表示执行ARM指令。
- ②T=1表示执行 Thumb指令。
- 对于ARMv5以及更高的版本的非T系列的ARM处理器,T控制位的含义如下
- ①T=0表示执行ARM指令。
- ②T=1表示强制下一条执行的指令产生未定义指令中断。
- M控制位
- 控制位M[40控制处理器模式,具体含义如下图所示。
4.CPSR中的其他位
CPSR中的其他位用于将来ARM版本的扩展。应用软件不要操作这些位,以免与ARM将来版本的扩展冲突。
3.ARM体系的异常中断
在ARM体系中,通常有以下3种方式控制程序的执行流程:
- 在正常程序执行过程中,每执行一条ARM指令,程序计数寄存器(PC)的值加4个字节;每执行一条 Thumb指令,程序计数寄存器(PC)的值加两个字节。整个过程是按顺序执行的
- 通过跳转指令,程序可以跳转到特定的地址标号处执行,或者跳转到特定的子程序处执行。其中,B指令用于执行跳转操作;BL指令在执行跳转操作的同时,保存子程序的返回地址;BX指令在执行跳转操作的同时,根据目标地址的最低位可以将程序状态切换到 Thumb状态;BLX指令执行3个操作,跳转到目标地址处执行,保存子程序的返回地址,根据目标地址的最低位可以将程序状态切换到 Thumb状态
- 当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执行。在异常中断处理程序执行完成后,程序返回到发生中断的指令的下一条指令处执行。在进入异常中断处理程序时,要保存被中断的程序的执行现场,在从异常中断处理程序退出时,要恢复被中断的程序的执行现场。
ARM处理器对异常中断的响应过程
- 保存处理器当前状态、中断屏蔽位以及各条件标志位。这是通过将当前程序状态寄存器CPsR的内容保存到将要执行的异常中断对应的 SPSR寄存器中实现的。各异常中断有自己的物理SPSR寄存器。
- 设置当前程序状态寄存器CPSR中相应的位。包括设置CPSR中的位,使处理器进入相应的执行模式:设置CPSR中的位,禁止IRQ中断,当进入FIQ模式时,禁止FQ中断
- 将寄存器 Ir_mode设置成返回地址。
- 将程序计数器(PC)设置成该异常中断的中断向量地址,从而跳转到相应的异常中
断处理程序处执行。
从异常中断处理程序中返回
- 恢复被中断的程序的处理器状态,即将 SPSR mode寄存器内容复制到CPSR中
- 返回到发生异常中断的指令的下一条指令处执行,即把 Ir mode寄存器的内容复制到程序计数器PC中。
在复位异常中断处理程序开始整个用户程序的执行,因而它不需要返回。
实际上,当异常中断发生时,程序计数器PC所指的位置对于各种不同的异常中断是不同的。同样,返回地址对于各种不同的异常中断也是不同的
4.ARM体系中的存储系统
ARM体系中的存储空间
ARM体系使用单一的地址空间。该地址空间的大小为232-1.
ARM的地址空间也可以看作是2^30个32位的字单元。这些字单元的地址可以被4整除,也就是说,该地址的低两位为0b00.地址为A的字数据包括地址为A、A+1、A+2A+3四个字节单元的内容。
在ARM4及以上的版本中,ARM的地址空间也可以看作是2个16位的半字单元。这些半字单元的地址可以被2整除,也就是说,该地址的最低位为0b0.地址为A的半字数据包括地址为A、A+1两个字节单元的内容.
各存储单元的地址作为32位的无符号数,可以进行常规的整数运算。这些运算的结果进行2^32取模。也就是说,运算结果发生上溢出和下溢出时,地址将会发生卷绕。
ARM存储器格式
在ARM体系中,每个字单元中包含4个字节单元或者两个半字单元:一个半字单元中包含两个字节单元。但是在字单元中,4个字节哪一个是高位字节,哪一个是低位字节则有两种不同的格式:Big- endian格式和 Little-endian格式。
在 Big-endian格式中,对于地址为A的字单元,包括字节单元A、A+1、A+2及A+3,其中字节单元由高位到低位字节顺序为A、A+1、A+2、A+3;地址为A的字单元包括半字单元A、A+2,其中半字单元由高位到低位字节顺序为A、A+2:地址为A的半字单元包括字节单元A、A+1,其中字节单元由高位到低位字节顺序为A、A+1.
在 Little-endian格式中,地址为A的字单元包括字节单元A、A+1、A+2及A+3,其中字节单元由高位到低位字节顺序为A+3、A+2、A+1、A;地址为A的字单元包括半字单元A、A+2,其中半字单元由高位到低位字节顺序为A+2、A:地址为A的半字单元包括字节单元A、A+1,其中字节单元由高位到低位字节顺序为A+1、A.
对比如下:
非对齐的存储访问操作
在ARM中,通常希望字单元的地址是字对齐的(地址的低两位为0b00),半字单元的地址是半字对齐的(地址的最低位为0b0).在存储访问操作中,如果存储单元的地址没有遵守上述对齐规则,则称为非对齐( Unaligned)的存储访问操作。
1.非对齐的指令预取操作
当处理器处于ARM状态期间,如果写入到寄存器PC中的值是非字对齐的(低两位不
为0b00),要么指令执行的结果不可预知,要么地址值中最低两位被忽略:当处理器于Thumb状态期间,如果写入到寄存器PC中的值是非半字对齐的(最低位不为0b0),要指
令执行的结果不可预知,要么地址值中最低位被忽略。如果系统中指定,当发生非对齐的指令预取操作时,忽略地址值中相应的位,则由存储系统实现这种“忽略”.也就是说,这时该地址值原封不动地送到存储系统。
2.非对齐的数据访问操作
对于 Load/Store操作,如果是非对齐的数据访问操作,则系统定义了下面3种可能的
结果
- 执行的结果不可预知。
- 忽略字单元地址的低两位的值,即访问地址为( Address AND0 xFFFFFFC)的字单元;忽略半字单元地址的最低位的值,即访问地址为( Address AND OxFFFFFFE的半字单元。
- 忽略字单元地址值中的低两位的值;忽略半字单元地址的最低位的值。由存储系统实现这种“忽略”.也就是说,这时该地址值原封不动地送到存储系统。
当发生非对齐的数据访问时,到底采用上述3种处理方法中的哪一种,是由各指令指定的。
指令预取和自修改代码
在ARM中允许指令预取。在CPU执行当前指令的同时,可以从存储器中预取其后若干条指令,具体预取多少条指令,不同的ARM实现中有不同的数值。
预取的指令并不一定能够得到执行。比如当前指令完成后,如果发生了异常中断,程序将会跳转到异常中断处理程序处执行,当前预取的指令将被抛弃。或者如果执行了跳转指令,则当前预取的指令也将被抛弃。
正如在不同的ARM实现中,预取的指令条数可能不同,当发生程序跳转时,不同的ARM实现中采用的跳转预测算法也可能不同。
自修改代码指的是代码在执行过程中可能修改自身。对于支持指令预取的ARM系统,自修改代码可能带来潜在的问题。当指令被预取后,在该指令被执行前,如果有数据访问指令修改了位于主存中的该指令,这时被预取的指令和主存中对应的指令不同,从而可能使执行的结果发生错误。
第2章 ARM指令分类及寻址方式
ARM指令集概述
分类
- 跳转指令
- 数据处理指令
- 程序状态寄存器传输指令
- Load/Store指令
- 处理器指令
- 异常中断产生指令
编码格式
固定长度32位,典型格式:
其中的符号及参数说明如下。
- opcode:指令操作符编码
- cond:指令执行的条件编码。
- S:决定指令的操作是否影响CPSR的值。
- Rd:目标寄存器编码。
- Rn:包含第1个操作数的寄存器编码。
- shifter operand:表示第2个操作数
一条典型的ARM指令语法格式如下所示
<opcode> {<cond>} {s} <Rd>, <Rn>, <shifter operand>
其中的符号及参数说明如下。
- < opcode>:是指令助记符,如ADD表示算术加操作指令
- {
}:表示指令执行的条件。可无 - {S}:决定指令的操作是否影响CPSR的值。可无
:表示目标寄存器 :表示包含第1个操作数的寄存器 - < shifter operand>:表示第2个操作数。
ARM指令的条件码域
最前面的4位是条件码,16个.只有符合条件的指令才执行,有一个条件码是无条件执行.
寻址方式
数据处理指令的操作数寻址方式
数据处理指令典型格式:<opcode> {<cond>} {s} <Rd>, <Rn>, <shifter operand>
<shifter operand>
表示第二个的操作数,通常有下面的3种格式
- 立即数寻址:语法格式
#<immediate>
- 立即数
由一个常数循环右移偶数位得到,8位常数记为 immed_8
,右移位数由一个4位的二进制数表示,记为rota
te_imm`. - ARM汇编器的规则:立即数数值在0~0xFF范围内时,不进行处理,大于0xFF时,选择
rotate_imm
数值最小的编码方式.
- 立即数
- 寄存器方式:操作数即是寄存器的数值,语法格式
<Rm>
- 寄存器移位方式:寄存器的数值在进行移位操作得到的值.
- ASR:算术右移,语法格式
<Rm>,ASR #<shift_imm>
,<Rm>,ASR <Rs>
- LSL:逻辑左移,语法格式
<Rm>,LSL #<shift_imm>
,<Rm>,LSL <Rs>
- LSR:逻辑右移,语法格式
<Rm>,LSR #<shift_imm>
,<Rm>,LSR <Rs>
- ROR:循环右移,语法格式
<Rm>,ROR #<shift_imm>
,<Rm>,ROR <Rs>
- RRX:扩张的循环右移,语法格式
<Rm>,RRX
- ASR:算术右移,语法格式
不是很懂,待理解
#<shift_imm>
是直接位移shift_imm位<Rs>
需要看<Rs>
的最低8位Rs[7:0]- 当Rs[7:0]=0时,指令的操作数< shifter operand>为寄存器Rm的数值,循环器的进位值为CPSR中的C条件标志位:
- 当Rs[7:0]>0且Rs[7:0]<32时,指令的操作数< shifter operand为寄存器Rm的数值移动Rs[7:0]位,循环器的进位值为Rm最后被移出的位Rm[Rs[7:0]-1];
- 当Rs[7:0]=32时,将进行32次移动操作,
- 这时若Rm[31]=0,则操作数< shifter operand>值为0,循环器的进位值即Rm的最高位Rm[31]也为0:
- 若Rm[31]=1,则操作数< shifter operand>值为0 xFFFFFFFF,,循环器的进位值Rm的最高位Rm[31]也为1.
- RRX指令的操作数
<shifter_operand>
为寄存器Rm的数值右移一位,并用CPSR中的C条件标志位填补空出的位。CPSR中的C条件标志位则用移出的位代替。
字及无符号字节的Load/Store指令的寻址方式
- Load指令用于从内存中读取数据放入寄存器中
- Store指令用于将寄存器中的数据保存到内存中
LDR指令格式
- cond为指令执行的条件编码。
- I、P、U、W等位的含义在后面将详细地说明。
- Rd为目标寄存器编吗。
- Rn与 Address_mode一起构成第2个操作数的内存地址。(基地址和偏移地址)
LDR指令的语法格式LDR {<cond>}{B} {IT} <Rd>,<address mode>
其中,<address_mode>
表示第2个操作数的内存地址,共有如下9种格式:
[<Rn>,#+/-<offset_12>
- 内存地址 address为基址寄存器的值加上/减去偏移量 offset2.当U=1时, address为基址寄存器的值加上偏移量 offset12:当U=0时, address为基址寄存器的值减去偏移量offset12.
[<Rn>,+/-<Rm>]
[<Rn>,+/-<Rm>,<shift>#<shift_imm>]
[<Rn>,#+/-<offset_12>]!
[<Rn>,+/-<Rm>]!
[<Rn>,+/-<Rm>, <shift>#<shift_imm>]!
[<Rn>],#+/-<offse_12>
[<Rn>],+/-<Rm>
[<Rn>],+/-<Rm>,<shift>#<shift_imm>
写到这里觉得有点无聊,先不整理了
杂类Load/Store指令的寻址方式
批量Load/Store指令的寻址方式
协处理器Load/Store指令的寻址方式
第3章 ARM指令集介绍
ARM 指令集
分类:
- 跳转指令
- 数据处理指令
- 程序状态寄存器传输指令
- Load/Store指令
- 协处理器指令
- 异常中断产生指令