《ARM体系结构与编程》学习笔记

第1章 ARM概述及编程模型

这一章讲了ARM的一些基本概念,和ARM的编程模型.
编程模型:运行模式,寄存器,异常中断,存储系统

一.概述(略)

  1. 了解ARM体系结构的版本
  2. 了解ARM体系的变种(Thumb指令集,长乘法指令集…)
  3. ARM/Thumb体系版本命名
  4. 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)。在所有的寄存器中,有些是各模式共用的同一个物理寄存器:有一些寄存器是各模式自己拥有的独立的物理寄存器。
下图列出了各种处理器模式下可见的寄存器情况。

《ARM体系结构与编程》学习笔记 - 图1

通用寄存器

通用寄存器可以分为下面3类:

  • 未备份寄存器( Unbanked Registers ),包括RO~R7
  • 备份寄存器( Banked Registers),包括R8~R|4
  • 程序计数器PC,即R15
  1. 未备份寄存器,在各个处理器模式下用的都是同一个寄存器。
  2. 备份寄存器在不同的处理器模式下用的寄存器不同。
    1. 比如:R13常用作栈指针,不同模式下,我们标记为R13_,mode可以是usrsveabtundiqfiq
    2. R14被称为连接寄存器:一般保存子程序的返回地址,或异常模式要返回的地址。
  3. 程序寄存器R15(PC):当前指令地址值加8个字节,避免用STR/STM保存R15的值(可能会保存加12的值),和芯片的实现方式有关

程序状态寄存器

CPSR(当前程序状态寄存器)可以在任何处理器模式下被访问。它包含了条件标志位、中断禁止位、当前处理器模式标志以及其他的一些控制和状态位。每一种处理器模式下都有一个专用的物理状态寄存器,称为SPSR(备份程序状态寄存器).当特定的异常中断发生时,这个寄存器用于存放当前程序状态寄存器的内容。在异常中断程序退出时,可以用
SPSR中保存的值来恢复CPSR.

由于用户模式和系统模式不是异常中断模式,所以它们没有SPSR.当在用户模式或
系统模式中访问SPSR时,将会产生不可预知的结果。

CPSR的格式如下图所示。SPSR格式与CPSR格式相同。

《ARM体系结构与编程》学习笔记 - 图2

1.条件标志位
N( Negative)、Z(zero)、c(Cary)及 V(oVerflow)统称为条件标志位。大部分的ARM指令可以根据CPSR中的这些条件标志位来选择性地执行。各条件标志位的具体含义如下图所示。

《ARM体系结构与编程》学习笔记 - 图3

以下指令会影响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控制处理器模式,具体含义如下图所示。

《ARM体系结构与编程》学习笔记 - 图4

4.CPSR中的其他位
CPSR中的其他位用于将来ARM版本的扩展。应用软件不要操作这些位,以免与ARM将来版本的扩展冲突。

3.ARM体系的异常中断

在ARM体系中,通常有以下3种方式控制程序的执行流程:

  • 在正常程序执行过程中,每执行一条ARM指令,程序计数寄存器(PC)的值加4个字节;每执行一条 Thumb指令,程序计数寄存器(PC)的值加两个字节。整个过程是按顺序执行的
  • 通过跳转指令,程序可以跳转到特定的地址标号处执行,或者跳转到特定的子程序处执行。其中,B指令用于执行跳转操作;BL指令在执行跳转操作的同时,保存子程序的返回地址;BX指令在执行跳转操作的同时,根据目标地址的最低位可以将程序状态切换到 Thumb状态;BLX指令执行3个操作,跳转到目标地址处执行,保存子程序的返回地址,根据目标地址的最低位可以将程序状态切换到 Thumb状态
  • 当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执行。在异常中断处理程序执行完成后,程序返回到发生中断的指令的下一条指令处执行。在进入异常中断处理程序时,要保存被中断的程序的执行现场,在从异常中断处理程序退出时,要恢复被中断的程序的执行现场。

《ARM体系结构与编程》学习笔记 - 图5

ARM处理器对异常中断的响应过程

  1. 保存处理器当前状态、中断屏蔽位以及各条件标志位。这是通过将当前程序状态寄存器CPsR的内容保存到将要执行的异常中断对应的 SPSR寄存器中实现的。各异常中断有自己的物理SPSR寄存器。
  2. 设置当前程序状态寄存器CPSR中相应的位。包括设置CPSR中的位,使处理器进入相应的执行模式:设置CPSR中的位,禁止IRQ中断,当进入FIQ模式时,禁止FQ中断
  3. 将寄存器 Ir_mode设置成返回地址。
  4. 将程序计数器(PC)设置成该异常中断的中断向量地址,从而跳转到相应的异常中
    断处理程序处执行。

从异常中断处理程序中返回

  1. 恢复被中断的程序的处理器状态,即将 SPSR mode寄存器内容复制到CPSR中
  2. 返回到发生异常中断的指令的下一条指令处执行,即把 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体系结构与编程》学习笔记 - 图6

非对齐的存储访问操作

在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位,典型格式:

《ARM体系结构与编程》学习笔记 - 图7

其中的符号及参数说明如下。

  • 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个.只有符合条件的指令才执行,有一个条件码是无条件执行.

《ARM体系结构与编程》学习笔记 - 图8

寻址方式

数据处理指令的操作数寻址方式

数据处理指令典型格式:
<opcode> {<cond>} {s} <Rd>, <Rn>, <shifter operand>

<shifter operand>表示第二个的操作数,通常有下面的3种格式

  1. 立即数寻址:语法格式#<immediate>
    1. 立即数由一个常数循环右移偶数位得到,8位常数记为immed_8,右移位数由一个4位的二进制数表示,记为rotate_imm`.
    2. ARM汇编器的规则:立即数数值在0~0xFF范围内时,不进行处理,大于0xFF时,选择rotate_imm数值最小的编码方式.
  2. 寄存器方式:操作数即是寄存器的数值,语法格式<Rm>
  3. 寄存器移位方式:寄存器的数值在进行移位操作得到的值.
    • 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

不是很懂,待理解

  • #<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指令格式

《ARM体系结构与编程》学习笔记 - 图9

  • 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指令
  • 协处理器指令
  • 异常中断产生指令

跳转指令

数据处理指令

程序状态寄存器传输指令

Load/Store指令

协处理器指令

异常中断产生指令

第4章 ARM汇编语言程序设计

第5章 ARM的存储系统

第6章 ATPCS介绍

第7章 ARM程序和Thumb程序混合使用

第8章 C/C++以及汇编语言的混合编程

第9章 异常中断处理

第10章 ARM C/C++编译器

第11章 ARM连接器

第12章 嵌入式应用程序示例

第13章 使用CodeWarrior

第14章 ARM体系中的调试方法