ARM③——异常模式

ARM③——异常模式&异常源&向量表

一、异常(异常模式)

tips:这里的异常并不是熟知的error错误等异常,而是质的异常模式(除去user和system模式)

1、异常源

alt

异常源 异常模式
复位(RESET) SVC
未定义指令 undef
软中断(swi) SVC
预取指令异常 Abort
数据异常 Abort
IRQ IRQ
FIQ FIQ

2、异常向量表

alt

为什么FIQ 比 IRQ要快?

  1. FIQ拥有更多的独立寄存器
  2. 异常向量表处在最下方,跳转更快捷
  3. 优先级更高

3、切换异常模式的大概流程

alt

① 触发异常

② 保护现场

  • 异常模式的spsr = cpsr 记录跳转前的状态
  • 保存跳转前指令运行的地址 异常模式_lr = pc

③ 切换模式

​ cpsr = xx异常模式 修改CPSR的模式位

④ 跳转到异常向量表

⑤ 跳转到异常处理函数

  • 压栈 lr
  • 判断具体异常类型
  • 跳转到处理函数

⑥ 具体处理函数

  • 压栈
  • 具体处理
  • 出栈

⑦ 准备切换回异常前的模式 和 还原CPSR

ldmfd sp!,{r0-r12,pc}^

4、不同异常返回地址

alt

alt

二、软中断(汇编示例)

#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

全部评论

相关推荐

03-08 18:11
门头沟学院 Java
Java抽象小篮子:海投就完事了,简历没什么问题,最大问题是学历
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务