中断流程:①发生中断操作。②程序跳转至相应中断处理函数。③保存现场、处理功能、恢复现场。④程序跳转正常模式继续运行
注:本文将以软中断swi 2指令,在SVC与user两种模式的切换做详细解释。
先来看发生中断时候的特定函数
这里我们先开辟两个空间,存放发生中断后寄存器内容以及lr寄存器内的中断的下调命令地址。
.data
.stack_svc:@svc模式下的sp寄存器
.space 100@开辟100字节
.stack_svc_end:@函数结束
.stack_user: @user模式下的sp寄存器
.space 100
.stack_user_end:
因为当前是svc模式,所以我们先将svc开辟的空间地址给到它的sp寄存器,同时写好异常向量表。然后告诉编译器我们的开始地址,这里以reset函数为起始函数
.gloal _start @告诉编译器从哪里开始读取
_start: @从这里开始往下走
.text @接下来是代码段
b reset @当前模式下的起始入口 地址为0x00 也可以写为ldr pc,=reset
nop @b undfine_hander@未定义中断,这里用不到,但为了符合向量表就先写上
b swi_hander @发生软中断时的跳转入口 地址为0x08 异常向量表简单的写两个即可
nop
nop
nop
nop
nop@预留异常向量表的地址
reset:@抒写初始函数功能
ldr sp,=stack_svc @将开辟好的栈区空间首地址给svc模式下的sp寄存器(此时为svc模式)
mrs r0,cprs @将cprs当前的状态放至r0,当前时svc模式(10011),所以我们需要间接去改变它
bic r0,#0x1f @先清空r0状态内容
mov r0,#0x10 @将r0改为user模式
msr cprs,r0 @将r0的值放置cprs中更改当前模式为user(10000)
ldr sp,=stack_user@将开辟好的栈区空间首地址给user模式下的sp寄存器(此时为user模式)
mov r0,#1 @开始在user模式下操作寄存器
mov r2,#2
swi 2@采用open操作,这里开始发生软中断反应
sub r3,r1,r0 @为了验证跳出时,寄存器内容是否依旧为跳转前的内容
swi_hander: 软中断的跳转函数
stmfd sp!,{r0-r12,lr}@入栈操作
mov r0,#0xff
mov r1,#0xad @操作当前模式下的寄存器
sub r3,lr,#4 @获取跳转指令的地址(swi 2)
ldr r4,[r3] @获取跳转指令的机器码至寄存器4
bic r4,#0xff000000 @保存机器指码的后两位
cmp r4,#2 @分析跳转指令是否为软中断2号指令
movne r5,0x55
moveq r5,0x66 @若为软中断2号指令则将寄存器r5改为0x66,不是则0x55
swi_hander_end: @软中断跳转函数结束
ldm sp!,{r0-r12,pc} @出栈操作,恢复现场。同时跳转到发生中断的后一条指令准备执行