• ARM 异常处理过程,指令[ swi ]


    1.  发生异常:

      程序正常执行,突然被一个不正常的事件打断正在执行的程序,执行相应的异常事件对应的程序

    2.  5 种异常模式对应着 7 种异常源:

              异常工作模式           异常源
              FIR                      FIR

              IRQ                     IRQ

                Abort           data_abort / pref_abort

               Undef                     undefine

              SVC                                    reset复位 / swi软中断指令

    3. 同种异常源不可以被打断,reset 优先级最高,打断任何程序执行

    4. 异常处理过程:

      

        保护现场:由 CPU 自动完成,通过 4 步完成 ; 通用寄存器CPSR 中的状态,改变CPU状态

        (1)CPU 保存现场当前状态 CPSR 到异常模式下的 SPSR 中 ,这步的目的是保护当前状态的CPSR(每种异常模式都对应一个自己的SPSR,以便将来在异常返回时,从SPSR恢复至CPSR)

        (2)CPU 修改 CPSR 中 模式位,禁止相应中断源,切换 CPU 状态为ARM 状态(Thumb态和ARM态由CPSR的T位来决定)

          (3)保存的返回地址到对应异常模式下的LR 寄存器中。(返回地址:异常发生前正在执行指令的下一条地址)

          (4)pc 指向异常向量表中对应的异常

          恢复现场: 需要自己手动完成(手动修改寄存器 CPSR 中对应的状态位)

         (1) 把异常模式下的 SPSR_MODE 恢复到CPSR中

          (2)把 异常模式下的 LR_MODE 恢复到 PC中

    5. 异常向量表
      1)异常向量表就是内存的一块空间,这块内存的空间的大小为32byte,平均分成了8份,每份4个byte,然后在里边存放7中异常源,多余的一份保留不用
      2) 在异常量表中存放的一条跳转指令
      3) 7种异常源在异常向量表中的位置固定,不可以随意更改。

    示例: 手动修改到user模式,然后使用 swi 软中断切换到 SVC 异常模式

    .text
    .global _start
    _start:
        b reset_handler
        b undef_handler
        b swi_handler
        b pref_abort_handler
        b data_abort_handler
        b .
        b irq_handler
        b fiq_handler
        
    reset_handler:           @ 复位开始为 SVC 模式
        ldr sp, =0x40000200  @ 初始化栈
        mrs r0, cpsr           @ 读取程序状态寄存器
        mov r1, #0x1F
        mvn r1, r1
        and r0, r0, r1
        mov r1, #0x10
        orr r0, r0, r1       @ 修改 读取 的CPSR 中的数据, 然后再重新写入CPSR 寄存器
        msr cpsr, r0         @ 保存状态寄存器 此时改为 user 模式
        ldr sp, =0x40000100  @ 初始化此状态下的 sp 指针
        swi #1                  @ 使用指令 swi 产生异常,异常号为 1
        mov r0, #1
        mov r1, #2
        swi #2                 @ 使用指令 swi 产生异常,异常号为 2
        mov r0, #1
        mov r1, #2
    loop:
        b loop
    
    undef_handler:
    swi_handler:     @ 切换模式后, 先进行现场保护, cpsr和lr值保存,修改cpsr切换模式
    .if 0
        stmfd sp!, {r0-r10, lr}  @ 入栈  拷贝过来的lr 值, lr内容没有改变
        mov r0, #1
        mov r1, #2
        ldmfd sp!, {r0-r10, r12} @ 出栈
        mrs r11, spsr
        msr cpsr, r11
        mov pc, r12    @ 恢复现场
    .else
        stmfd sp!, {r0-r12, lr}
        mov r0, #1
        mov r1, #2
    
        mov r0, lr   
        sub r0, r0, #4       @ 获取 lr 上一条指令(也就是swi)的地址
        ldr r1, [r0]         @ 提取 swi 指令对应的机器码
        ldr r2, =0xFFFFFF     @ 提取后24位 对应的 num号
        and r0, r1, r2          @根据r0判断具体是哪个地方的swi
        
        ldmfd sp!, {r0-r12, pc}^  @ 恢复现场, ^ 表示同时操作两个步骤
    .endif
    
    pref_abort_handler:
    data_abort_handler:
    irq_handler:
    fiq_handler:
        
    .end

  • 相关阅读:
    生手和FinallyJane一起学习ASP.NET
    使用eclipse 初学java
    关于C#中用access做数据库,使用like语句的问题(转)
    VSS (Visual Source Safe 2005) 用法详解(转)
    mysql 字符集问题之我见
    mysqli的预处理功能使用
    兼容IE和Firefox
    linux下netsnmp 已经安装,为什么没有 snmpwalk和snmpget
    ? PHP WBEM
    安装cacti时提示错误
  • 原文地址:https://www.cnblogs.com/electronic/p/11027136.html
Copyright © 2020-2023  润新知