ARM③——异常模式
ARM③——异常模式&异常源&向量表
一、异常(异常模式)
tips:这里的异常并不是熟知的error错误等异常,而是质的异常模式(除去user和system模式)1、异常源
异常源 异常模式 复位(RESET) SVC 未定义指令 undef 软中断(swi) SVC 预取指令异常 Abort 数据异常 Abort IRQ IRQ FIQ FIQ 2、异常向量表
为什么FIQ 比 IRQ要快?
- FIQ拥有更多的独立寄存器
- 异常向量表处在最下方,跳转更快捷
- 优先级更高
3、切换异常模式的大概流程
① 触发异常
② 保护现场
- 异常模式的spsr = cpsr 记录跳转前的状态
- 保存跳转前指令运行的地址 异常模式_lr = pc
③ 切换模式
cpsr = xx异常模式 修改CPSR的模式位
④ 跳转到异常向量表
⑤ 跳转到异常处理函数
- 压栈 lr
- 判断具体异常类型
- 跳转到处理函数
⑥ 具体处理函数
- 压栈
- 具体处理
- 出栈
⑦ 准备切换回异常前的模式 和 还原CPSR
ldmfd sp!,{r0-r12,pc}^4、不同异常返回地址
二、软中断(汇编示例)
#include <asm-offsets.h>
#include <config.h>
#include <version.h>
#include <asm/system.h>
#include <linux/linkage.h>
.globl _start
_start: b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction: .word _undefined_instruction
_software_interrupt: .word software_handerl
_prefetch_abort: .word _prefetch_abort
_data_abort: .word _data_abort
_not_used: .word _not_used
_irq: .word _irq
_fiq: .word _fiq
_pad: .word 0x12345678 /* now 16*4=64 */
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3 @110 10011 设置为svc并且禁用中断,ARM指令
msr cpsr,r0
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
mcr p15, 0, r0, c12, c0, 0 @Set VBAR @设置协处理器
/*设置svc的栈*/
ldr r0, =stack_top
ldr r0, [r0]
mov sp, r0
ldr r1, =stack
/*切换到user模式*/
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd0 @1101 0000 设置为user并且禁用中断,ARM指令
msr cpsr,r0
/*设置usre的栈*/
ldr r0, =stack_top
ldr r0, [r0]
sub r0, r0, #224
mov sp, r0
bl _main
_main:
mov r0, #1
mov r1, #2
bl user_sub
nop
nop
user_add:
stmfd sp!, {r0-r8, lr}
swi 0
ldmfd sp!, {r0-r8, pc}
user_sub:
stmfd sp!, {r0-r8, lr}
swi 1
ldmfd sp!, {r0-r8, pc}
software_handerl:
stmfd sp!, {r0-r8, lr}
sub r0, lr, #4 @lr-4 为上一条指令的地址
ldr r0, [r0]
and r0, #0x1
cmp r0, #0x1
blne sys_add
bleq sys_sub
ldmfd sp!, {r0-r8, pc}^ /*pc = lr cpsr = spsr*/
sys_add:
stmfd sp!, {r0-r8, lr}
add r9, r1, r0
ldmfd sp!, {r0-r8, pc}
sys_sub:
stmfd sp!, {r0-r8, lr}
sub r9, r1, r0
ldmfd sp!, {r0-r8, pc}
stack:
.space 56*8
stack_top:
.word stack+56*8
查看21道真题和解析