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 {
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 register),中文称号:当时程序状况寄存器,望文生义它是用于保存程序的当时状况的。那么,程序的哪些状况是需求保存的呢?
上图是CPSR寄存器的内容,主要由以下部分组成:
1、条件代码标志位。它们是ARM指令条件履行的根据。
N:运算成果的最高位反映在该标志位。关于有符号二进制补码,成果为负数时N=1,成果为正数或零时N=0;
Z:指令成果为0时Z=1(一般表明比较成果“持平”),不然Z=0;
C:当进行加法运算(包含CMN指令),而且最高位产生进位时C=1,不然C=0。当进行减法运算(包含CMP 指令),而且最高位产生借位时C=0,不然C=1。关于结合移位操作的非加法/减法指令,C为从最高位最终移出的值,其它指令C一般不变
V:当进行加法/减法运算,而且产生有符号溢出时V=1,不然V=0,其它指令V一般不变
2、操控位。它们将操控CPU是否呼应间断。
I:间断制止位,当I方位位时,IRQ间断被制止
F:快间断制止位,当F方位位时,FIQ间断被制止
T:反映了CPU当时的状况。当T方位位时,处理器正在Thumb状况下运转;当T位清零时,处理器正在ARM状况下运转
3、形式位
包含M4、M3、M2、M1和M0,这些位决议了处理器的形式(关于处理器形式详见“ARM处理器形式与反常开始”一文)。
一共有7种形式:用户、快间断、间断、办理、间断、未界说、体系,别离会用于不同的状况和反常。由此可见,不是一切形式位的组合都界说了有用的处理器形式,假如运用了过错的设置,将引起一个无法康复的过错。
SPSR(saved program status register),中文称号:保存的程序状况寄存器
该寄存器的结构与CPSR彻底相同,在反常产生时(关于反常,请拜见“ARM处理器形式与反常开始”一文),由硬件主动将反常产生前的CPSR的值寄存到SPSR中,以便将来在反常处理完毕后,程序能康复本来CPSR的值。