ARM基本数据类型
ARM 采用的是32位架构,ARM的基本数据类型有以下3种。
- Byte:字节,8bit。
- Halfword:半字,16bit(半字必须于2字节边界对齐)。
- Word:字,32bit(字必须于4字节边界对齐)。
存储器可以看作是序号为 0~232−1 的线性字节阵列。图下图所示为ARM存储器的组织结构。
存储器大/小端
从软件角度看,内存相对于一个大的字节数组,其中每个数组元素(字节)都是可寻址的。
ARM 支持大端模式(big-endian)和小端模式(little-endian)两种内存模式。下图分别显示了内存的大端模式和小端模式。
处理器工作模式
ARM处理器有两种安全级别:特权级和用户级。共有7种工作模式,用户模式(User)、系统模式(Systerm)、快速中断模式(FIQ)、外部中断模式(IRQ)、特权模式(Supervisor)、数据访问中止模式(Abort)、未定义指令中止模式(Undef),除了用户模式之外其他工作模式都属于特权模式,6种特权模式除了系统模式之外其他的都是异常模式,对应着7异常(异常相关的内容放到异常章节介绍)。详细的工作模式如下表所示。
处理器模式可以通过软件控制进行切换,也可以通过外部中断或异常处理过程进行切换。大多数的用户程序运行在用户模式下。当处理器工作在用户模式时,应用程序不能够访问受操作系统保护的一些系统资源,应用程序也不能直接进行处理器模式切换。当需要进行处理器模式切换时,应用程序可以产生异常处理,在异常处理过程中进行处理器模式切换。
当应用程序发生异常中断时,处理器进入相应的异常模式。在每一种异常模式中都有一组专用寄存器以供相应的异常处理程序使用,这样就可以保证在进入异常模式时用户模式下的寄存器(保存程序运行状态)不被破坏。
系统模式,不能有任何异常进入。仅ARM体系结构v4及以上版本有该模式。它和用户模式具有完全相同的寄存器。但是系统模式属于特权模式,可以访问所有的系统资源,也可以直接进行处理器模式切换,它主要供操作系统任务使用。通常操作系统的任务需要访问所有的系统资源,同时该任务仍然使用用户模式的寄存器组而不是异常模式下相应的寄存器组,这样可以保证当异常中断发生时任务状态不被破坏。
ARM寄存器组织
ARM处理器有37个32位长的寄存器。
- 1 个用作 PC(Program Counter)。
- 1 个用作 CPSR(Current Program Status Register)。
- 5 个用作 SPSR(Saved Program Status Registers)。
- 30 个用作通用寄存
ARM处理器共有7种不同的处理器模式,在每一种处理器模式中有一组相应的寄存器组。下表2显示了ARM的寄存器组织概要。
注意
System 模式使用和 User 模式相同的寄存器集
当前处理器的模式决定着哪组寄存器可操作,任何模式都可以存取。
- 相应的 r0~r12。
- 相应的 r13(the stack pointer, sp)和 r14(the link register, lr)。
- 相应的 r15(the program counter, pc)。
- 相应的 CPSR(current program status register, cpsr)。
特权模式(除 System 模式)还可以存取。 - 相应的 SPSR(saved program status register)。
通用寄存器
通用寄存器根据其分组与否和使用目的分为以下3类。
- 未分组寄存器(The unbanked registers),包括r0~r7。
- 分组寄存器(The banked register),包括r8~r14。
- 程序计数器(Program Counter),即r15。
1.未分组寄存器
未分组寄存器包括r0~r7。顾名思义,在所有处理器模式下对于每一个未分组寄存器来说,指的都是同一个物理寄存器。未分组寄存器没有被系统用于特殊的用途,任何可采用通用寄存器的应用场合都可以使用未分组寄存器。但由于其通用性,在异常中断所引起的处理器模式切换时,其使用的是相同的物理寄存器,所以也就很容易使寄存器中的数据被破坏。
2. 分组寄存器
r8~r14是分组寄存器,它们每一个访问的物理寄存器取决于当前的处理器模式。
对于这些分组寄存器r8~r12来说,每个寄存器对应两个不同的物理寄存器。一组用于除FIQ模式外的所有处理器模式,而另一组则专门用于FIQ模式。这样的结构设计有利于加快FIQ的处理速度。不同模式下寄存器的使用,要使用寄存器名后缀加以区分,例如,当使用FIQ模式下的寄存器时,寄存器r8和寄存器r9分别记做r8_fiq, r9_fiq;当使用用户模式下的寄存器时,寄存器r8和r9分别记做r8_usr, r9_usr 等。在ARM体系结构中,r8~r12 没有任何指定的其他的用途,所以当FIQ中断到达时,不用保存这些通用寄存器,也就是说FIQ处理程序可以不必执行保存和恢复中断现场的指令,从而可以使中断处理过程非常迅速。所以FIQ模式常被用来处理一些时间紧急的任务。
对于分组寄存器r13和r14来说,每个寄存器对应6个不同的物理寄存器。其中的一个是用户模式和系统模式公用的,而另外5个分别用于5种异常模式。访问时需要指定它们的模式。名字形式如下:
- r13_<mode>
- r14_<mode>
其中可以是以下几种模式之一:usr、svc、abt、und、irp 及 fiq。
r13寄存器在ARM中常用作堆栈指针,称为SP。当然,这只是一种习惯用法,并没有任何指令强制性的使用r13作为堆栈指针,用户完全可以使用其他寄存器作为堆栈指针。而在Thumb指令集中,有一些指令强制性的将r13作为堆栈指针,如堆栈操作指令。
每一种异常模式拥有自己的 r13。异常处理程序负责初始化自己的r13,使其指向该异常模式专用的栈地址。在异常处理程序入口处,将用到的其他寄存器的值保存在堆栈中,返回时,重新将这些值加载到寄存器。通过这种保护程序现场的方法,异常不会破坏被其中断的程序现场。
寄存器r14又被称为连接寄存器(Link Register,LR),在 ARM 体系结构中具有下面两种特殊的作用。
(1)每一种处理器模式用自己的r14存放当前子程序的返回地址。当通过BL或BLX指令调用子程序时,r14被设置成该子程序的返回地址。在子程序返回时,把r14的值复制到程序计数器 PC。典型的做法是使用下列两种方法之一。
- 执行下面任何一条指令。
MOV PC, LR
BX LR
- 在子程序入口处使用下面的指令将PC保存到堆栈中。
STMFD SP!, {<register>, LR}
在子程序返回时,使用如下相应的配套指令返回。
LDMFD SP!, {<register>, PC}
(2)当异常中断发生时,该异常模式特定的物理寄存器r14被设置成该异常模式的返回地址,对于有些模式r14的值可能与返回地址有一个常数的偏移量(如数据异常使用 SUB PC, LR,#8 返回)。具体的返回方式与上面的子程序返回方式基本相同,但使用的指令稍微有些不
同,以保证当异常出现时正在执行的程序的状态被完整保存。R14也可以被用作通用寄存器使用。
注意
当嵌套中断被允许时(即异常可重入),r13和r14的使用要特别小心。例如,在用户模式下一个IRQ中断发生,这时两种模式分别使用不同的r13和r14,换句话讲,用户模式使用 r13_usr和r14_usr,而IRQ模式使用r13_irq和r14_irq,这样不会造成寄存器使用冲突。但是,当程序运行在IRQ模式下,又有IRQ中断进入,此时,第二级中断使用r13_irq 和 r14_irq,冲掉了第一级 IRQ 的堆栈指针和返回地址,导致程序异常。解决办法是在第二级中断发生前,将第一级中断用到的寄存器压栈。
程序计数器 r15
程序计算器r15又被记为PC。用于控制程序中指令的执行顺序。CPU正常运行时,PC指向CPU运行的下一条指令地址。每次取指后PC的值会自动修改以指向下一条指令,从而保证了指令按一定的顺序执行。当程序的执行发生改变时,需要修改PC的的值。R15也可以用作通用寄存器,但一般不这么用,因为对R15的使用有一些特殊的限制。当违反了这些指令的使用限制时,指令的执行结果是不可预知的。
程序计数器在下面两种情况下用于特殊的目的。
- 读程序计数器。
- 写程序计数器。
1.程序计数器读操作
由于ARM的流水线机制,指令读出的r15的值是指令地址加上8个字节。由于ARM指令始终是字对齐的,所以读出的结果位[1∶0]始终是0(但在Thumb状态下,指令为2字节对齐,bit[0]=0)。
2.程序计数器写操作
当指令向r15写入地址数据时,如果指令成功返回,它将使程序跳转到该地址执行。由于ARM指令是字对齐的,写入r15的地址值应满足bit[1:0]=0b00,具体的规则根据ARM版本的不同也有所不同:
- 对于ARM版本3以及更低的版本,写入r15的地址值 bit[1:0]被忽略,即写入r15的地址值将与0xFFFFFFFC做与操作。
- 对于ARM版本4以及更高的版本,程序必须保证写入r15寄存器的地址值的bit[1:0]为 0b00,否则将会产生不可预知的结果。
对于Thumb指令集来说,指令是半字对齐的。处理器将忽略bit[0],即写入r15寄存器的值在写入前要先和0XFFFFFFFE做与操作。
有些指令对r15的操作有特殊的要求。比如,指令BX利用bit[0]来确定需要跳转到的子程序是ARM状态还是Thumb状态。
程序状态寄存器
当前程序状态寄存器 CPSR(Current Program Status Register)可以在任何处理器模式下被访问,它包含下列内容。
- ALU(Arithmetic Logic Unit)状态标志的备份。
- 当前的处理器模式。
- 中断使能标志。
- 设置处理器的状态(只在4T架构)。
每一种处理器模式下都有一个专用的物理寄存器作备份程序状态寄存器SPSR(Saved Program Status Register)。当特定的异常中断发生时,这个物理寄存器负责存放当前程序状态寄存器的内容。当异常处理程序返回时,再将其内容恢复到当前程序状态寄存器。
注意
由于用户模式和系统模式不属于异常中断模式,所以它们没有SPSR。当在用户模式或系统模式中访问SPSR,将会产生不可预知的结果。
CPSR寄存器(和保存它的SPSR寄存器)中的位分配如下图所示。
1.标志位
N(Negative)、Z(Zero)、C(Carry)和 V(oVerflow)通称为条件标志位。这些条件标志位会根据程序中的算术或逻辑指令的执行结果进行修改,而且这些条件标志位可由大多数指令检测以决定指令是否执行。在ARM 4T架构中,所有的ARM指令都可以条件执行,而Thumb指令却不能。
各条件标志位的具体含义如下。
- N
本位设置成当前指令运行结果的 bit[31]的值。当两个由补码表示的有符号整数运算时,N=1 表示运算的结果为负数;N=0 表示结果为正数或零。
- Z
Z=1 表示运算的结果为零,Z=0 表示运算的结果不为零。
- C
下面分 4 种情况讨论 C 的设置方法。
① 在加法指令中(包括比较指令 CMN),当结果产生了进位,则 C=1,表示无符号数运算发生上溢出;其他情况下 C=0。
② 在减法指令中(包括比较指令 CMP),当运算中发生错位(即无符号数运算发生下溢出),则 C=0,;其他情况下 C=1。
③ 对于在操作数中包含移位操作的运算指令(非加/减法指令),C 被设置成被移位寄存器最后移出去的位。
④ 对于其他非加/减法运算指令,C 的值通常不受影响。
- V
下面分两种情况讨论V的设置方法。
① 对于加/减运算指令,当操作数和运算结果都是以二进制的补码表示的带符号的数时,V=1 表示符号位溢出。
② 对于非加/减法指令,通常不改变标志位 V 的值(具体可参照 ARM 指令手册)尽管以上C和V的定义看起来颇为复杂,但使用时在大多数情况下用一个简单的条件测试指令即可,不需要程序员计算出条件码的精确值即可得到需要的结果。
控制位
CPSR的低8位(I、F、T 及 M[4∶0])统称为控制位。当异常发生时,这些位的值将发生相应的变化。另外,如果在特权模式下,也可以通过软件编程来修改这些位的值。
① 中断禁止位
I=1,IRQ 被禁止。
F=1,FIQ 被禁止。
② 状态控制位
T 位是处理器的状态控制位。
T=0,处理器处于 ARM 状态(即正在执行 32 位的 ARM 指令)。
T=1,处理器处于 Thumb 状态(即正在执行 16 位的 Thumb 指令)。
当然,T 位只有在 T 系列的 ARM 处理器上才有效,在非 T 系列的 ARM 版本中,T 位将始终为 0。
③ 模式控制位
M[4∶0]作为位模式控制位,这些位的组合确定了处理器处于哪种状态。下列出了其具体含义。只有表中列出的组合是有效的,其他组合无效。
注意
由于用户模式(User)和系统模式(System)是非异常模式,所以没有单独的 SPSR 保存程序状态字。在用户模式或系统模式下,读 SPSR 将返回一个不可预知的值,而写 SPSR 将被忽略。
THUMB 寄存器
Thumb状态下的寄存器集是ARM状态下寄存器集的一个子集,程序可以直接访问8个通用寄存器(R0~R7)、程序计数器(PC)、堆栈指针(SP)、连接寄存器(LR)和CPSR。同时,在每一种特权模式下都有一组SP、LR和SPSR。如下图是Thumb状态下的寄存器组织。
Thumb状态下的寄存器组织雨ARM状态下的寄存器组织的关系:
>>Thumb状态下和ARM状态下的R0h~R7是相同的。
>>Thumb状态下和ARM状态下的CPSR和所有的SPSR是相同的。
>>Thumb状态下的SP对应ARM状态下的R13。
>>Thumb状态下的LR对应ARM状态下的R14。
>>Thumb状态下的程序计数器对应ARM 状态下的R15。
以上的对应关系如下图所示。
Thumb 状态下,不能直接访问所有的处理器寄存器,只有 r0~r7 是可以被任意访问的,在 Thumb 状态下使用该 8 个寄存器和在 ARM状态下使用没有区别。寄存器 r8~r12 只能通过 MOV、ADD 或 CMP 指令访问。CMP 指令和所有操作 r0~r7 的数据处理指令都会影响 CPSR 中的条件标志位。一些 Thumb 指令还使用到了程序计数器 PC(r15),链接地址寄存器 LR(r14)和堆栈指针寄存器 SP(r13)。在 Thumb状态下,读取 r15 寄存器时,bit[0]值为 0,bit [31∶1]包含了 PC 的值。当对 r15 进行写入时,bit[0]被忽略,bit[31∶1]被设置成当前程序计数器的值。下表 列出了 Thumb 状态下,各寄存器的使用情况。
从上表可以看出,Thumb 状态下不能直接访问 CPSR 和 SPSR。也就是没有和MSR 和 MRS 等价的指令。为了改变 CPSR 和 SPSR 的值,必须使处理器状态切换到 ARM状态,再使用指令 MSR 和 MRS 来实现。同样,在 Thumb 状态下也没有协处理器访问指令,要访问协处理器寄存器来配置 cache 和进行内存管理,也必须使处理器切换到ARM 状态。
注意 Thumb 状态下,对 CPSR 的条件标准位控制由算术和逻辑操作设置并控制条件转移。
总结
从ARM的编程模型来看,内容似乎不多,看起来也很简单,相比CM3内核似乎内容少的很多。相比较而言,ARM内核更加复杂,CM3的很多操作有硬件完成,而ARM更多是有软件来处理,即ARM的灵活度更高,难度更大。