Cortex-M3处理器拥有R0~R15的寄存器组,如:
【R0~R12通用寄存器】
R0~R12都是32位通用寄存器,用于数据操作。其中:
- R0~R7为低组寄存器,所有的指令都可以访问。
- R8~R12为高组寄存器,只有32位Thumb2指令和很少的16位Thumb指令能访问。
【R13堆栈指针SP】
Cortex-M3拥有两个堆栈指针,然而它们是banked,任一时刻只能使用其中的一个。
- 主堆栈指针(MSP):复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理(包括中断服务)。
- 进程堆栈指针(PSP):由用户的应用程序代码使用。
【R14连接寄存器LR】
连接寄存器LR用于在调用子程序时存储返回地址。例如,在使用BL(分支变连接,Branch and Link)指令时,就自动填充LR的值。
main ;主程序 ... BL function1 ; 使用“分支并连接”指令调用function1 ; PC=function1,并且LR=main的下一条指令地址 ... function1 ... ; function1的代码 BX LR ; 函数返回(如果function1要使用LR,必须使用前PUSH, ; 否则返回时程序就可能跑飞了)
ARM为了减少访问内存的次数(访问内存的操作往往需要3个以上指令周期,带MMU和cache的就更加不确定了),把返回地址直接存储在寄存器中。这样足以使很多只有1级子程序调用的代码无需访问内存(堆栈内存),从而提高了子程序调用的效率。如果多于1级,则需要把前一级的R14值压到堆栈里。
在ARM上编程时,应尽量只使用寄存器保存中间结果,迫不得已才访问内存。
在RISC处理器中,为了强调访问内存操作越过了处理器的界线,并且带来了对性能的不利影响,给它取了一个专业的术语:溅出。
【R15程序计数寄存器PC】
程序计数寄存器PC指向当前的程序地址。如果修改它的值,能改变程序的执行流。
因为Cortex-M3内部使用了指令流水线,读PC时返回的值时当前指令的地址值+4,如:
0x1000: MOV R0, PC ; R0 = 0x1004
如果向PC中写数据,就会引起一次程序的分支(但是不更新LR寄存器)。
Cortex-M3中的指令至少是半字(2字节)对齐的,所以PC的LSB总是读回0。然而,在分支时,无论是直接写PC的值还是使用分支指令,都必须保证价值到PC的数值是奇数(即LSB=1),用以表明这是在Thumb状态下执行。如若写了0,则视为企图转入ARM模式,Cortex-M3将产生一个fault异常。
参考摘录:《ARM Cortex-M3权威指南.pdf》