ARM汇编编程基础之一-寄存器
ARM寄存器分为2类,普通寄存器和状态寄存器
寄存器类别 | 寄存器在汇编中的名称 | 各模式下实际访问的寄存器 | ||||||
用户 | 系统 | 管理 | 中止 | 未定义 | 中断 | 快中断 | ||
通用寄存器和程序计数器 | R0(a1) | R0 | ||||||
R1(a2) | R1 | |||||||
R2(a3) | R2 | |||||||
R3(a4) | R3 | |||||||
R4(v1) | R4 | |||||||
R5(v2) | R5 | |||||||
R6(v3) | R6 | |||||||
R7(v4) | R7 | |||||||
R8(v5) | R8 | R8_fiq | ||||||
R9(SB,v6) | R9 | R9_fiq | ||||||
R10(SL,v7) | R10 | R10_fiq | ||||||
R11(FP,v8) | R11 | R11_fiq | ||||||
R12(IP) | R12 | R12_fiq | ||||||
R13(SP) | R13 | R13_svc | R13_abt | R13_und | R13_irq | R13_fiq | ||
R14(LR) | R14 | R14_svc | R14_abt | R14_und | R14_irq | R14_fiq | ||
R15(PC) | R15 | |||||||
状态寄存器 | CPSR | CPSR | ||||||
SPSR | 无 | SPSR_abt | SPSR_abt | SPSR_und | SPSR_irq | SPSR_fiq |
请看上表的第2列,普通寄存器总共16个,分别为R0-R15;状态寄存器共2个,分别为CPSR和SPSR
普通寄存器中特别要提出来的是R13、R14、R15。
R15别名PC(program counter),中文称为程序计数器,它的值是当前正在执行的指令在内存中的位置(不考虑流水线的影响,参见流水线对PC值的影响一文),而当指令执行结束后,CPU硬件会自动将PC的值加上一个单位,从而使得PC的值为下一条即将执行的指令在内存中的位置,这样CPU硬件就可以根据PC的值自动完成取指的操作。正是由于有PC的存在,以及CPU硬件会自动增加PC的值,并根据PC的值完成取指操作,才使得CPU一旦上电就永不停歇地运转,由此可见PC寄存器对于计算机的重要性。对于我们进行汇编程序编写而言,PC寄存器亦是十分重要,因为当程序员通过汇编指令完成了对PC寄存器的赋值操作的时候,其实就是完成了一次无条件跳转,这一点非常重要,请务必要牢记。
R14别名LR(linked register),中文称为链接寄存器,它与子程序调用密切相关,用于存放子程序的返回地址,它是ARM程序实现子程序调用的关键所在。下面我们用C语言中对子程序调用的实现细节来说明LR是如何被使用的。
1 int main(void)
2 {
3
4
5
6 }
7 int addsub(int a, int b)
8 {
9
10
11
12 }
对于上面的程序,编译器会将第4行编译为指令:BL addsub,将第11行编译为指令:MOV pc, lr。(关于BL和MOV指令详见“基本寻址模式与基本指令”)
在这里,关键指令BL addsub会完成2件事情:1、将子程序的返回地址(也就是第5行代码在内存中的位置)保存到寄存器LR中;2、跳转到子程序addsub的第1条指令处。这样就完成了子程序的调用。而指令MOV pc, lr则将保存在lr中的返回地址赋给pc,这样就完成了从子程序的返回。由此可见,lr是用于存放子程序的返回地址的。
另外一个要引起注意的问题是,如果子程序又调用了孙子程序,那么根据前面的分析,在调用孙子程序时,lr寄存器中的值将从子程序的返回地址变为孙子程序的返回地址,这将导致从孙子程序返回子程序没有问题,但从子程序返回父程序则会出错。那么这个问题如何解决呢?其实,如果我们编写的是C程序,那么我们一点也不用担心,因为编译器会为我们考虑一切,针对这个问题,编译器会在孙子程序的入口处增加入栈操作将lr的值入栈,然后在孙子程序的返回处增加出栈操作,将lr的值恢复,从而解决这个难题。不过我们一定要保持头脑的清醒,因为你要知道,我们现在是在编写汇编子程序,此时编译器已经不能在这方面给我们提供保障,所以当你在编写汇编子程序的时候,发现该子程序还要再调用孙子程序,那么请你务必记住,一定要在子程序的入口处保存lr寄存器的值。
好了,现在轮到寄存器R13了,R13又名SP(stack pointer),中文名称栈指针寄存器。顾名思义,它是用于存放堆栈的栈顶地址的。也就是说,每次当我们进行出栈和入栈的时候,都将根据该寄存器的值来决定访问内存的位置(即:出入栈的内存位置),同时在出栈和入栈操作完成后,SP寄存器的值也应该相应增加或减少。这里要特别说明的是,其实在32位的ARM指令集中没有专门的入栈指令和出栈指令,所以并不是一定要用SP来作为栈指针寄存器,除了PC外,任何普通寄存器均可作为栈指针寄存器,只不过,约定俗成都使用SP罢了。我们将在“其它寻址模式与其它指令”一文中见到ARM中使用SP作为栈指针寄存器的出入栈指令。
寄存器R0-R12是普通的数据寄存器,可用于任何地方。在不涉及ATPCS规则(在“ATPCS与混合编程”一文中详细介绍)的情况下,他们并没有什么特别的用法。
状态寄存器CPSR(current program status registe
ARM汇编编程寄存 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)