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