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

原文地址:https://www.cnblogs.com/electronic/p/11027136.html