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

 原文作者地址:http://user.qzone.qq.com/308337370/                                        原作者的大作,小弟钦慕而转载!

ARM的汇编编程,本质上就是针对CPU寄存器的编程,所以我们首先要弄清楚ARM有哪些寄存器?这些寄存器都是如何使用的?­

寄存器类别

寄存器在汇编中的名称

各模式下实际访问的寄存器

用户

系统

管理

中止

未定义

中断

快中断

通用寄存器和程序计数器

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 int k, i = 1, j = 2;­

4 addsub(i, j);­

5 k = 3;­

6 }  7 int addsub(int a, int b)­

8 {­

9 int c;­

10 c = a + b;­

11 return 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 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的值。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值