版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/M_N_N/article/details/82807683
上一帖总结了异常中断处理过程,当未定义指令异常发生时,PC最终会跳到0xFFFF0204
,该地址上也是一条跳转指令。为了执行我们自定义的异常处理函数,让这条指令跳向我们的函数即可;
接着 5_lds 写;
在启动文件中加入一条未定义指令;
.text
.global _start
_start: // 地址 0x42C00000
bl bss_init // .bss段初始化
.word 0xFFFF0000 // 无效指令,会产生Undef异常
b main
为了能直观的看到效果,进入自定义函数后串口打印提示信息;
void except_und(){
asm("stmdb sp!, {r0-r12, lr}\n"); // 保存现场,lr存的是产生undef异常的指令的下一条指令地址;
uart0_init(115200);
printf("Triggered undefined exceptions %d\r\n", 0);
asm("ldmia sp!, {r0-r12, pc}^\n"); // 恢复现场,'^'表示恢复CPSR;
}
编译,查看反汇编文件可以得到函数except_und()
的地址;
42c0016c <except_und>:
42c0016c: e92d4800 push {fp, lr}
42c00170: e28db004 add fp, sp, #4
42c00174: e92d5fff push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
42c00178: e3a00cc2 mov r0, #49664 ; 0xc200
42c0017c: e3400001 movt r0, #1
42c00180: eb00032f bl 42c00e44 <uart0_init>
42c00184: e301057c movw r0, #5500 ; 0x157c
42c00188: e34402c0 movt r0, #17088 ; 0x42c0
42c0018c: e3a01000 mov r1, #0
42c00190: eb0002d6 bl 42c00cf0 <printf>
42c00194: e8fd9fff ldm sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^
42c00198: e8bd8800 pop {fp, pc}
得到了要跳转的地址,将0x42c0016c赋值给PC,要占用两条指令的位置,0xFFFF0204
处可以修改为装载指令,0xFFFF0214
是一个保留地址,未使用,可以将要跳转的地址放在这里;
- 生成具体的二进制数据;
ldr pc, =0x42c0016c
.word 0x00000000
.word 0x00000000
.word 0x00000000
结果
FFFF0204: e59ff008 ldr pc, [pc, #8] ; 42c0001c <__TEXT_START+0x1c>
...
FFFF0214: 42c0016c sbcmi r0, r0, #108, 2
- 用WinHex修改SD卡数据,拷贝main.bin
上电
输出了提示信息;
CPU执行流程:
42c00000 <__TEXT_START>: // 裸机程序开始地址
42c00000: eb000029 bl 42c000ac <bss_init>
42c00004: ffff0000 ; <UNDEFINED> instruction: 0xffff0000
42c00008: ea000047 b 42c0012c <main>
...
42c0016c <except_und>: // Undef异常处理函数
42c0016c: e92d4800 push {fp, lr}
42c00170: e28db004 add fp, sp, #4
42c00174: e92d5fff push {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr}
42c00178: e3a00cc2 mov r0, #49664 ; 0xc200
42c0017c: e3400001 movt r0, #1
42c00180: eb00032f bl 42c00e44 <uart0_init>
42c00184: e301057c movw r0, #5500 ; 0x157c
42c00188: e34402c0 movt r0, #17088 ; 0x42c0
42c0018c: e3a01000 mov r1, #0
42c00190: eb0002d6 bl 42c00cf0 <printf>
42c00194: e8fd9fff ldm sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, pc}^
42c00198: e8bd8800 pop {fp, pc}
当CPU执行到42c00004
时产生Undef异常,PC跳到0x34000004(IROM)
,然后跳到0xFFFF0004(NSIH)
,然后跳到0xFFFF0204(2NBOOT)
,
而0xFFFF0204
是我们修改后的指令,PC再跳自定义的异常处理函数0x42c0016c
,先保存现场,处理完后恢复现场,再回到异常指令的下一条指令,即main()
;