zoukankan      html  css  js  c++  java
  • ARM处理器模式切换(含MRS,MSR指令)

    除了用户模式和系统模式,其余模式下都有一个私有SPSR保存状态寄存器,用来保存切换到该模式之前的执行状态,之所以用户模式和系统模式没有SPSR是因为,通常CPU大部分时间执行在用户模式下,当产生异常或系统调用时会分别切换进入另外几种模式,保存用户模式下的状态,当切换回原先模式时,直接回复SPSR的值到CPSR就可以了,因此,用户模式和系统模式下不需要SPSR,其详细操作查看下节异常处理。

    以上几种模式通过CPSR里的M[4:0]位进行区分,如图3-1所示:

     

     

    图3-1 CPSR控制位

    通过向模式位M[4:0]里写入相应的数据切换到不同的模式,在对CPSR,SPSR寄存器进行操作不能使用mov,ldr等通用指令,只能使用特权指令msr和mrs。

    在ARM处理器中,只有MRS(Move to Register from State register)指令可以对状态寄存器CPSR和SPSR进行读操作。通过读CPSR可以获得当前处理器的工作状态。读SPSR寄存器可以获得进入异常前的处理器状态(因为只有异常模式下有SPSR寄存器)。

    例如:

    MRS    R1,CPSR   ; 将CPSR状态寄存器读取,保存到R1中

    MRS    R2,SPSR    ; 将SPSR状态寄存器读取,保存到R2中

    通过MRS指令可以取得状态寄存器里的值,然后比较其模式位M[4:0]的值判断当前所处模式,当然也可以比较其它相应位了解当前CPU的状态。

    同样,在ARM处理器中,只有MSR指令可以对状态寄存器CPSR和SPSR进行写操作。与MRS配合使用,可以实现对CPSR或SPSR寄存器的读-修改-写操作,可以切换处理器模式、或者允许/禁止IRQ/FIQ中断等。

    由于xPSR寄存器代表了CPU的状态,其每个位有特殊意义,在执行对xPSR状态寄存器写入时(读取时不存在该用法),为了防止误操作和方便记忆,将xPSR里32位分成四个区域,每个区域用小写字母表示:

    c  控制域屏蔽 psr[7..0]

    x  扩展域屏蔽 psr[15..8]

    s  状态域屏蔽 psr[23..16]

    f  标志域屏蔽 psr[31..24]

    注意:区域名必须为小写字母

    向对应区域进行执行写入时,使用xPSR_x可以指定写入区域,而不影响状态寄存器其它位,如:

    使能IRQ中断:

    ENABLE_IRQ

        MRS    R0, CPSR            ; 将CPSR寄存器内容读出到R0

        BIC    R0, R0,#0x80     ; 清掉CPSR中的I控制位

        MSR    CPSR_c,R0          ; 将修改后的值写回 CPSR寄存器的对应控制域

        MOV    PC,LR                       ; 返回上一层函数

    禁用IRQ中断:

    DISABLE_IRQ

        MRS    R0 CPSR                          ; 将CPSR寄存器内容读出到R0

        ORR    R0, R0,#0x80    ; 设置CPSR中的I控制位

        MSR    CPSR_c,R0          ; 将修改后的值写回 CPSR寄存器的对应控制域

        MOV    PC,LR                          ; 返回上一层函数

    下表列出了不同模式的二进制数表示:

    表3-3 不同工作模式对应二进制

    模式名

    用户

    快中断

    中断

    管理

    中止

    未定义

    系统

    M[4:0]

    10000

    10001

    10010

    10011

    10111

    11011

    11111

    在对开发板进行初始化时,用对不同模式指定其栈空间,下面例子对各模式的栈指针sp进行初始化:

    stack_init                                                            ; 栈指针初始化函数

        @ undefine_stack                                       

        msr cpsr_c, #0xdb                                   ; 切换到未定义异常

        ldr        sp, =0x34000000                        ; 栈指针为内存最高地址,栈为倒生的栈

                                                                                ; 栈空间的最后1M 0x34000000~0x33f00000

        @ abort_stack                                                      

        msr cpsr_c, #0xd7                                   ; 切换到终止异常模式

        ldr        sp, =0x33f00000                         ; 栈空间为1M,0x33f00000~0x33e00000

        @ irq_stack                                                

        msr      cpsr_c,    #0xd2                           ; 切换到中断模式

        ldr        sp, =0x33e00000                        ; 栈空间为1M,0x33e00000~0x33d00000

        @ sys_stack                                               

        msr      cpsr_c,    #0xdf                                     ; 切换到系统模式

        ldr        sp, =0x33d00000                        ; 栈空间为1M,0x33d00000~0x33c00000

        msr      cpsr_c,    #0xd3                            ; 切换回管理模式

        mov pc, lr

  • 相关阅读:
    【POJ 1958】 Strange Towers of Hanoi
    【HNOI 2003】 激光炸弹
    【POJ 3263】 Tallest Cow
    【POJ 2689】 Prime Distance
    【POJ 2777】 Count Color
    【POJ 1995】 Raising Modulo Numbers
    【POJ 1845】 Sumdiv
    6月16日省中集训题解
    【TJOI 2018】数学计算
    【POJ 1275】 Cashier Employment
  • 原文地址:https://www.cnblogs.com/cdwodm/p/2965379.html
Copyright © 2011-2022 走看看