微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM汇编编程基础之一-寄存器

ARM汇编编程基础之一-寄存器

时间:11-27 来源:互联网 点击:
ARM汇编编程,本质上就是针对CPU寄存器的编程,所以我们首先要弄清楚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 {
3int k, i = 1, j = 2;
4addsub(i, j);
5k = 3;
6 }

7 int addsub(int a, int b)
8 {
9int c;
10c = a + b;
11return c;
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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top