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