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