ARM V7寄存器

/*
 * 2012/3/30 10:23 yin
 */

ARM处理器含有37个寄存器,这些寄存器包括以下两类寄存器。

(1)31个通用寄存器:包括程序计数器PC等,这些寄存器都是32位寄存器。

(2)6个状态寄存器:状态寄存器也是32位的寄存器,但是只使用了其中的12位。

(3)NEON寄存器是Q0~Q15共计16个

 
/*
 * 通用寄存器
 */

    在ARM处理器的7种模式下都有一组对应的寄存器组。在任意时刻,可见的寄存器组包括15个通用寄存器R0~R14、

    一个或两个状态寄存器和PC。在所有的寄存器中,有些是各种模式下共用的同一个物理寄存器,

    有些是各种模式自己独立拥有的物理寄存器。详细如表1-3所示。

    表1-3 ARM物理寄存器

    用户模式  系统模式  特权模式  中止模式  未定义指令模  外部中断模  快速中断模
    
    R0 R0 R0 R0 R0 R0 R0
    
    R1 R1 R1 R1 R1 R1 R1

    R2 R2 R2 R2 R2 R2 R2
    
    R3 R3 R3 R3 R3 R3 R3

    R4 R4 R4 R4 R4 R4 R4
    
    R5 R5 R5 R5 R5 R5 R5
    
    R6 R6 R6 R6 R6 R6 R6
    
    R7 R7 R7 R7 R7 R7 R7
    
    R8 R8 R8 R8 R8 R8 R8_fiq
    
    R9 R9 R9 R9 R9 R9 R9_fiq
    
    R10 R10 R10 R10 R10 R10 R10_fiq
    
    R11 R11 R11 R11 R11 R11 R11_fiq
    
    R12 R12 R12 R12 R12 R12 R12_fiq
    
    R13 R13 R13_svc R13_abt R13_und R13_irq R13_fiq
    
    R14 R14 R14_svc R14_abt R14_und R14_irq R14_fiq
    
    PC PC PC PC PC PC PC
    
    CPSR CPSR CPSR CPSR CPSR CPSR CPSR
    
      SPSR_svc SPSR_abt SPSR_und SPSR_irq SPSR_fiq
    

    通用寄存器通常又可以分为下面3类。

    n  未备份寄存器:包括R0~R7。

    n  备份寄存器:包括R8~R14。

    n  程序计数器PC:即R15。

    1)未备份寄存器R0~R7


    对于每个未备份寄存器来说,在所有的处理器模式下指的都是同一个物理寄存器,在异常中断造成处理器模式切换时,

    由于不同的处理器模式使用相同的物理寄存器,可能造成寄存器中数据被破坏。未备份寄存器没有被系统用于特别的用途,

    任何可采用通用寄存器的应用场合都可以使用未备份寄存器。


    Arm的工作模式以及相关寄存器设置:

    1.用户模式(usr)         [10000]:ARM处理器正常的程序执行状态

    2.快速中断模式(fiq)  [10001]:用于高速数据传输或通道处理

    3.外部中断模式(irq)  [10010]:用于通用的中断处理

    4.管理模式(svc)    [10011]:操作系统使用的保护模式

    5.中止模式(abt)    [10111]:当数据或指令预取终止时进入该模式,用于虚拟存储及存储保护

    6.未定义指令模式(und) [11011]:当未定义的指令执行时进入该模式,用于支持硬件协处理器的软件仿真

    7.系统模式(sys)    [11111]:运行具有特权模式的操作系统任务

/*
 * R0-R12
 */
    用来在通用操作中存储临时的值,指针等。
    
    R0被用来存储函数调用的返回值。
    
    R7经常被用作存储系统调用号,
    
    R11存放着帮助我们找到栈帧边界的指针。
    
    以及,在ARM的函数调用约定中,前四个参数按顺序存放在R0-R3中。

/*
 * 备份寄存器R8~R14
 */

    备份寄存器中的每个寄存器对应于两个不同的物理寄存器。例如,当使用快速中断模式下的寄存器时,寄存器R8和寄存器R9分别记做R8_fiq和 R9_fiq,

    当使用用户模式下的寄存器时,寄存器R8和寄存器R9分别记做R8_usr和R9_usr等。


    在这两种情况下使用的是不同的物理寄存器,系统没有将这几个寄存器用于任何的特殊用途。中断处理非常简单,仅仅使用R8~R14寄存器时,

    FIQ处理程序可以不必执行保存和恢复中断现场的指令,从而可以使中断处理过程很迅速。

    对于备份寄存器R13、R14来说,每个寄存器对应于6个不同的物理寄存器,其中的一个是用户模式和系统模式共用的,

    另外的5个则对应于其他5种处理器模式


/*
 * FP (R11)
 */

FP: (Frame Pointer)初始化帧指针寄存器 ,fp为帧寄存器,起 "标签" 作用。

    每一种体系结构都有这么个一个东西,当调用一个c函数,必须有一个寄存器来指明局部变量区域的位置,函数推出后堆栈的位置和上一层的局部变量的区域。

    这个其实是编译系统中活动记录的东西。

    c 函数会使用堆栈,故而会使用sp寄存器, 但函数执行完后要恢复sp寄存器,通常会保留原来的寄存器,我们把它叫old-sp寄存器。
    arm 用fp寄存器充当这个角色。
        
    'frame pointer 在函数生命期内其值是不变的。

    局部变量是保存在堆栈中的,函数退出即丢弃。'通过frame pointer 可以获得局部变量的地址。


/*
 * IP (R12)
 */

    内部过程调用寄存器

    它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。
    在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 r12。


/*
 * SP (R13)
 */

    R13_<mode>,其中<mode>是usr、svc、abt、und、irq和fiq的一种。

    R13通常用做堆栈指针<"SP">。每一种模式都拥有自己的物理R13。程序初始化R13,使其指向该模式专用的栈地址。

    当进入该模式时,可以将需要使用的寄存器保存在R13所指的栈中,当退出该模式时,将保存在R13所指的栈中的寄存器值弹出。这样就实现了程序的现场保护。

    R13:SP(栈指针)。栈指针寄存器用来指向当前的栈顶。栈是一片来存储函数调用中相关数据的内存,在函数返回时会被修改为对应的栈指针。
    
    栈指针用来帮助在栈上申请数据空间。比如说你要申请一个字的大小,就会将栈指针减4,再将数据放入之前所指向的位置。


    用户模式和系统模式共用一个SP,每种异常模式都有各自专用的R13寄存器(SP)。它们通常指向各模式所对应的专

    用堆栈,也就是ARM处理器允许用户程序有六个不同的堆栈空间


/*
 * LR (R14)
 */

    寄存器R14又被称为连接寄存器("LR"),在ARM中有下面两种特殊用途。

    ① 每一种处理器模式在自己的物理R14中存放当前子程序的返回地址。当通过BL或者BLX指令调用子程序时,

        R14被设置成该子程序的返回地址。在子程序中,当把R14的值复制到程序计数器PC中时,就实现了子程序返回。


    可以通过下面两种方式实现这种子程序的返回操作。

    ◆执行下面任何一条指令

        mov pc, lr
        bx    lr

    ◆在子程序入口使用下面指令将PC保存到栈中:

        STMFD  SP!, {registers}, LR}

        相应地,下面的指令可以实现子程序的返回:

        LDMFD  SP!, { registers}, LR }
    

    ② 当发生异常中断的时候,该模式下的特定物理R14被设置成该异常模式将要返回的地址。对于某些异常,

        R14的值可能与将返回的地址有一个常数的偏移量。具体的返回方式与上面的子程序返回方式基本相同。


    在ARM处理器中使用 R14实现对断点和调用点的记录,即使用R14用作返 回连接寄存器(LR)。在硬件上和指令执行上,CPU 自动完成相应返回点的记录。

    在ARM 汇编语言程序设计时,R14和LR通用。

    ARM处理器相应异常时,会自动完成将当前的PC保存到LR寄存器。

    ARM处理器执行子程序调用指令(BL )时,会自动完成将当前的PC的值减去4的结果数据保存到LR寄存器。即将调用指令的下紧邻指令的地址保存到LR。

    ARM处理器针对不同的模式,共有6个链接寄存器资源(LR ),其中用户模式和系统模式共用一个 LR,每种异常模式都有各自专用的R14 寄存器(LR )。
    
    这些链接寄存器分别为 R14、R14_svc、R14_abt、R14_und、R14_irq、R14_fiq,

    程序设计者要清晰处理器的模式与相应寄存器的对应关系,都是使用 R14,但不同模式下的R14 不是同一个物理资源,其内容可能天壤之别。

    R14 不用做链接寄存器(LR )时,也可以用做通用数据寄存器。

    R14:LR(链接寄存器)。
    当一个函数调用发生,链接寄存器就被用来记录函数调用发生所在位置的下一条指令的地址。这么做允许我们快速的从子函数返回到父函数。


    在ARM体系结构中LR的特殊用途有两种:
        一是执行子程序调用指令(BL )时,会自动完成将当前的PC的值减去4的结果数据保存到LR寄存器。
            即将调用指令的下紧邻指令的地址保存到LR。返回时将lr赋给pc即可

        二是当异常发生时,会自动完成将当前的PC保存到LR寄存器,返回时将lr-4赋给pc即可,因此在各种异常模式下可以根据LR的值
            返回到异常发生前的相应位置继续执行。

        为什么异常发生时,需要 sub lr, lr, #4 ?

            是因为arm流水线,也就是执行第1条指令,第2条指令进行译码,将第3条指令从存储器中取出,那么pc当前等于pc+8

            所以在异常发生时,此时lr=pc+8,但是pc+4是没有被执行的,所以异常返回时需要返回到(lr-4)地址上,执行已经译码的地址上.

/*
 * PC (R15)
 */

    R15 程序计数器PC→R15

    程序计数器R15又被记作<"PC">。它虽然可以作为一般的通用寄存器使用,但是有一些指令在使用R15时有一些特殊限制。
    
    当违反了这些限制时,该指令执行的结果将是不可预料的。

    由于ARM采用了流水线机制,当正确读取了PC的值时,该值为当前指令地址值加8个字节。

    也就是说,对于ARM指令集来说,PC指向当前指令的下两条指令的地址。由于ARM指令是字对齐的,PC值的第0位和第1位总为0。

    需要注意的是,当使用指令STR/STM保存R15时,保存的可能是当前指令地址值加8字节,也可能保存的是当前指令地址加12字节。

    到底是哪种方式,取决于芯片具体设计方式。无论如何,在同一芯片中,要么采用当前指令地址加8,

    要么采用当前指令地址加12,不能有些指令采用当前指令地址加8,另一些指令采用当前指令地址加12。

    因此对于用户来说,尽量避免使用STR/STM指令来保存R15的值。当不可避免这种使用方式时,

    可以先通过一些代码来确定所用的芯片使用的是哪种实现方式。

    假设R0指向可用的一个内存字,下面代码可以在R0指向的内存字中返回该芯片所采用的地址偏移量。

        sub        r1, pc, #4            @ R1中存放下面STR指令的地址
        str        pc, [r0]              @ 将PC=STR地址+offset保存到R0中
        ldr        r0, [r0]              @
        sub        r0, r0, r1            @ offset=PC-STR地址


    PC 代表程序计数器,流水线使用三个阶段,因此指令分为三个阶段执行:
    
    1.取指(从存储器装载一条指令);
    
    2.译码(识别将要被执行的指令);
    
    3.执行(处理 指令并将结果写回寄存器)。
    
    而R15(PC)总是指向"正在取指"的指令,而不是指向"正在执行"的指令或正在"译码"的指令。
    
    一般来说,人们习惯性约定 将"正在执行的指令作为参考点",称之为当前第一条指令,因此PC总是指向第三条指令。
    
    当ARM状态时,每条指令为4字节长,所以PC始终指向该指令地址 加8字节的地址,即:PC值=当前程序执行位置+8;

    ARM指令是三级流水线,取指,译指,执行时同时执行的,现在PC指向的是正在取指的地址,那么cpu正在译指的指令地址是PC-4
    
    (假设在ARM状态 下,一个指令占4个字节),cpu正在执行的指令地址是PC-8,也就是说PC所指向的地址和现在所执行的指令地址相差8。

    当突然发生中断的时候,保存的是PC的地址

    这样你就知道了,如果返回的时候返回PC,那么中间就有一个指令没有执行,所以用SUB pc lr-irq #4


    注意pc,在调试的时候显示的是当前指令地址,而用mov lr,pc的时候lr保存的是此指令向后数两条指令的地址,
    
    大家可以试一下用 mov pc,pc,结果得到的是跳转两条指令,这个原因是由于arm的流水线造成的,预取两条指令的结果.


    如何访问常量数据

        当前pc值加存放数据地址就是真实数据地址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值