当前位置:   article > 正文

[und&swi]异常模式_swi 和 undef 异常返回

swi 和 undef 异常返回


本文是基于韦东山视频的学习笔记

汇总点这

und 异常(无定义异常)

我们在执行 main 函数之前加入句子

.word 0xdeadc0de	//故意加入未定义句子
  • 1

首先,代码执行至此,出现了 und 异常,根据异常向量表

这里是引用

出现 und 异常后会跳转到 0x00000004 地址去处理异常,所以我们需要在0x00000004 加入处理异常的跳转:

_start:
	b reset	/* 0x00000000 */
	b und	/* 0x00000004 */
  • 1
  • 2
  • 3

而 und 写什么呢,根据上篇博文,大概笼统地可以理解为

  1. 保护现场
  2. 处理
  3. 恢复现场
_start:
	b reset	/* 0x30000000 */
//	ldr pc, =do_und	/* 0x30000004 */
	ldr pc, und_addr	

/* 这里为什么这么做
 * ldr pc, und_addr 强制加载到这里,这里再强制加载到 do_und
 * 如果不是,由于"ldr pc, =do_und" 是一条伪指令,do_und这个地址就会被编译器默认保存在编译文件最后的地址
 * 修改后就能达到:“直接跳到接着上一句的地址执行,而不用跳到最后的地址”的目的
 */
und_addr:
	.word do_und

do_und:
	/* 重要!栈未设置,需要重新设置,指向一个不会被用到的地方 */
	ldr sp, =0x34000000
	
	/* 保护现场 */
	stmdb sp!, {r0-r12, lr}			//目前位置 lr 里面有异常前的下一条将要执行的指令,所以也要保存
	
	/* 处理异常 */
	mrs r0, cpsr	//读cpsr的值,作为print_und_exception的第一个参数
	ldr r1, =und_string	//r1 载入字符串,作为print_und_exception的第二个参数
	ldr pc, =print_und_exception

	/* 恢复现场 */
	ldmia sp!, {r0-r12, pc}^	/* ^会把spsr的值恢复到cpsr里 */

und_string:
	.string "und exception!!!"

.align (4)	// 4 zijie duiqi
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

swi 异常(软中断异常)

之前提过,除了usr模式之外,其他模式都可以都过寄存器任意切换,但恰恰app运行情况下一般情况都是usr模式。如果想切到其他模式,那就可以通过中断或者异常来实现,其中swi(软件异常)是最为常用的手段。软件异常进入的是svc模式。

事实上,swi 异常和 und 异常大同小异,照着印就可以。

swi  0x123	//加入swi异常
  • 1

这里是引用

代码都是大同小异

swi_addr:
	.word do_swi

do_swi:
	/* 重要!栈未设置,需要重新设置,指向一个不会被用到的地方 */
	ldr sp, =0x33e00000
	
	/* 保护现场 */
	stmdb sp!, {r0-r12, lr}			//目前位置 lr 里面有被打断前的下一条将要执行的指令,所以也要保存

	/* 调用c函数会破坏lr寄存器,所以要提前保护
 	 * 根据ATPCS规则,c函数调用完会恢复r4-r11的寄存器,所以可以r4来保存
	 */
	mov r4, lr	
	
	/* 处理异常 */
	mrs r0, cpsr	//读cpsr的值,作为print_swi_exception的第一个参数
	ldr r1, =swi_string	//r1 载入字符串,作为print_swi_exception的第二个参数
	bl print_swi_exception

	sub r0, r4, #4	/* lr是保存异常前下一条指令的地址,减4后,r0就是swi异常的句子*/
	bl print_swi_val

	/* 恢复现场 */
	ldmia sp!, {r0-r12, pc}^	/* ^会把spsr的值恢复到cpsr里 */
	
swi_string:
	.string "swi exception!!!"

.align (4)	// 前面是字串,后面必须4字节对齐
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

其中不同的是,swi异常的值是可以打印出来的,通过lr寄存器和print_swi_val函数实现的。

void print_swi_val(unsigned int *pswi)
{
	puts("\n\rswi_val = ");
	print_hex(*pswi & ~(0xff000000));
	puts("\n\r");
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/973545
推荐阅读
相关标签
  

闽ICP备14008679号