Cortex-m3与Cortex-m4处理器的寄存器组中有16个寄存器,其中13个为32位通用目的寄存器,其他3个则有特殊用途。
R0-R12
寄存器R0-R12为通用目的寄存器,前8个(R0-R7)也被称为低寄存器。由于指令中可用的空间有限,许多16位指令只能访问低寄存器。高寄存器(R8-R12)则可以用于32位指令和几个16位指令,如MOV。R0-R12的初始值是未定义的。
R13栈指针(SP)
R13 为栈指针,可通过 PUSH 和 POP 操作实现栈存储的访问。物理上存在两个栈指针:主栈指针(MSP,有些 ARM 文献也称其为 SP main)为默认的栈指针,在复位后或处理器处于处理模式时,其会被处理器选择使用。另外一个栈指针名为进程栈指针(PSP,有些ARM 文献也称其为 SP_process),其只能用于线程模式。栈指针的选择由特殊寄存器 CONTROL 决定。对于一般的程序,这两个寄存器只会有一个可见。MSP 和 PSP 都是 32位的,不过栈指针(MSP或PSP)的最低两位总是为0,对这两位的写操作不起作用。对于 ARM Cortex-M 处理器,PUSH 和 POP 总是 32位的,栈操作的地址也必须对齐到32位的字边界上。大多情况下,若应用不需要嵌入式 OS,PSP 也没必要使用。许多简单的应用可以完全依赖于 MSP,一般在用到嵌人式 OS时才会使用 PSP,此时 OS内核同应用任务的栈是相互独立的。PSP的初始值未定义,而MSP的初始值则需要在复位流程中从存储器的第一个字中取出。
R14,链接寄存器(LR)
R14 也被称作链接寄存器(LR),用于函数或子程序调用时返回地址的保存。在函数或子程序结束时,程序控制可以通过将1R的数值加载程序计数器(PC)中返回调用程序处并继续执行。当执行了函数或子程序调用后,LR的数值会自动更新。若某函数需要调用另外一个函数或子程序,则它需要首先将 LR的数值保存在栈中,否则,当执行了函数调用后,LR的当前值会丢失。在异常处理期间,LR也会被自动更新为特殊的 EXC RETURN(异常返回)数值,之后该数值会在异常处理结束时触发异常返回。本书第8章将会对这方面进行更加深入的介绍。尽管 Cortex-M 处理器中的返回地址数值总是偶数(由于指令会对齐到半字地址上,因此,第0位为 0),LR的第0位为可读可写的,有些跳转/调用操作需要将 LR(或正使用的任何寄存器)的第0 位置1以表示 Thumb 状态。
R15,程序计数器(PC)
R15 为程序计数器(PC),是可读可写的,读操作返回当前指令地址加4(由于设计的流水线特性及同 ARM7TDMI处理器兼容的需要)。写PC(例如,使用数据传输/处理指令)会引起跳转操作。由于指令必须要对齐到半字或字地址,PC的最低位(LSB)为0。不过,在使用一些跳转/读存储器指令更新 PC 时,需要将新 PC 值的 LSB 置1以表示 Thumb 状态,否则就会由于试图使用不支持的 ARM 指令(如 ARM7TDMI中的 32 位 ARM 指令)而触发错误异常。对于高级编程语言(包括C和C++),编译器会自动将跳转目标的LSB 置位。多数情况下,跳转和调用由专门的指令实现,利用数据处理指令更新 PC的情况较为少见。不过,在访问位于程序存储器中的字符数据时,PC的数值非常有用,因此,会经常发现存储器读操作将PC作为基地址寄存器,而地址偏移则由指令中的立即数生成。
程序中使用的寄存器名
对于多数汇编工具,在访问寄存器组中的寄存器时可以使用多种名称。在一些汇编工具中,如 ARM 汇编(被 DS-5 Professional 和 Keil MDK-ARM 支持),可以使用大写、小写或者大小写混合。