Arm汇编学习笔记(四)——ARM的37个寄存器和异常处理

ARM 126浏览

 

1. Arm的37个寄存器

看下面这张图:
可以看到User和System模式下的R0~R15和CPSR都是相同的寄存器,而在其它特权模式下用灰色三角形标注的那些寄存器,是该特权模式下特有的寄存器,比如在User模式下存入R8值0x50,切换到FIQ模式下存入R8值0x100,再切换回User模式下后,R8寄存器的值还是0x50。
这样算一下R0~R15在加上CPSR,然后在加上图中所有灰色三角标注的寄存器的个数正好是37个。

2. 异常处理

Arm在执行指令的过程中如果遇到异常,会跳转到异常向量表中对应的位置去处理,这里只是介绍异常向量表的作用,以及遇到异常后的执行流程。
异常向量表是约定好了的,但是异常向量表的内容是可以改变的,其定义如下:
上图对应了各种异常的情况下,程序跳转的地址。例如如果出现未定义的指令时,系统会切换到UND为定义模式,并跳转到0x00000004位置去执行,然而那个位置只有四字节可以执行,实际上那个位置只是一条跳转指令,会跳转到真正的处理函数,而这个真正的处理函数就叫做stub。
举个例子,加入我们在开发板上作业的话,就可以将下面内容放到0x0起始地址处,来实现自己的异常处理:
	b reset
	b und
	b swi
	b abt_pre
	b abt_dat
	.word 0
	b irq
	b fiq
 
 
 
 
reset:
	@stub, TODO
 
und:
	@stub
	adr r0, str
	ldr r3, printf
	mov lr, pc
	mov pc, r3
 
 
swi:
	@stub, TODO
 
abt_pre:
	@stub, TODO
 
abt_dat:
	@stub, TODO
 
irq:
	@stub, TODO
 
fiq:
	@stub, TODO
 
 
.extern printf
 
str:
	.asciz “undefined instr.\n”
上面代码只是为了实验,所以只实现了UND的处理函数stub,其它的只是声明了一下。在0x00000000处的指令是"b reset",会跳转到reset标签的位置去执行;而0x00000004处的指令是"b und",当发生未定义指令异常的时候就会跳转到und标签位置去处理了,这里我们只是输出了一个字符串"undefined instr."。
那么什么情况下会出现未定义指令异常呢?例如下面代码中的0x7777777
.global main
 
main:
	mov ip, sp
	stmfd sp!, {fp, ip, lr, pc}
	sub fp, ip, #4
 
	.word 0x77777777
 
	sub sp, fp, #12
	ldmfd sp!, {fp, sp, pc}

将上面代码编译成可执行文件后,用arm-linux-androideabi-objdump -d命令把反汇编得到下面内容:

00000234 <main>:
 234:	e1a0c00d 	mov	ip, sp
 238:	e92dd800 	push	{fp, ip, lr, pc}
 23c:	e24cb004 	sub	fp, ip, #4
 240:	77777777 			; <UNDEFINED> instruction: 0x77777777
 244:	e24bd00c 	sub	sp, fp, #12
 248:	e8bda800 	pop	{fp, sp, pc}

可以看到0x7777777是一条未定义指令,系统就会产生未定义异常。

上面的内容具体可以看视频:http://v.youku.com/v_show/id_XNTQ0MDk2MjAw.html?f=19177600&from=y1.2-3.4.5