EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
举个小例子,下面是一段ARM汇编代码: | 地址 | 指令 | 0x3000 | BL add | 0x3004 | MOV r0,#0 | 0x3008 | MOV r1,#1 | 0x300C | MOV r2,#2 | 2 |% I$ f4 J# `# f
AREA test,CODE,READONLY6 N5 [+ y) M( k1 `& [/ u$ O
ENTRY
- G& i5 ^: I5 S4 y/ K8 q Start
; r2 Q; K4 G. @( \+ ]2 v5 O MOV r0,#18 T0 l; X1 t# z( U6 J& J1 B% I
MOV r1,#1$ L% a- }5 j* m" x- N# q
BL add
3 W* z$ l# Y: W) u+ q) u, a MOV r0,#0
* H5 Z& ~1 D4 o) a0 K MOV r1,#1
9 a$ L4 b: `" p! e Add: S3 L0 \( h# }
ADD r0,r0,r1$ O1 n6 j% I" E; D3 H+ u8 J; |3 s
MOV r0,r0,r1
$ C. F) k+ Q, `4 t. n END 当0x3000处的BL指令执行时,会把PC(=0x3008)保存到LR寄存器里面,也就是LR=0x3008。接下来处理器会立即对LR进行一个自动的更新动作:LR=LR-0x4,这样,LR里面的地址为0x3008 – 0x4 = 03004,它是指令”MOV r0,#0”的地址,所以当从子程序add返回时,LR里面正好是正确的返回地址。既是下一条要执行的指令的地址。 (2)中断异常处理函数调用/ Q7 j8 ~/ G. r. l
异常就是正在执行的指令,由于各种软件或硬件故障被打断,比如,在读数据或指令时,访问存储器失败、产生了一个外部硬件中断等。当这些情况发生时,在ARM系统里,由异常和中断处理程序做出相应的处理,当处理完成后,要返回到被中止的指令,使被中止的指令能够继续正常执行下去。因此,确定异常和中断处理程序的返回地址是一个非常重要的问题。 1、中断处理 当外部中断IRQ和FIQ(Fast Interrpt Request,快速中断请求)发生时,ARM核完成一部分工作。当然,这些工作是任何异常发生时都必须要做的,所以ARM处理器就会自动带我们完成。 其它重要的工作,必须由程序员来完成。ARM处理器处理的事包括从用户模式切换到IRQ模式、状态寄存器值的变化及跳转。比如说,处理器自动跳转到从0x0地址开始的异常中断向量表的0x18处,在向量表的0x18处,最简单的指令为”B HandlerIRQ”。 那程序员所要关心的就是实现具体的异常处理程序(HandlerIRQ)。当用ARM汇编语言实现HandlerIRQ函数的时候,如何确定HandlerIRQ函数正确地返回地址,使被中止的指令能够继续正常执行下去。 比较常用的中断处理程序结构如下: HandlerIRQ ;中断响应,从向量表直接跳来 SUB r14,r14,#4 ;计算返回地址 STMFD r13,{r0-r3,r14} ;保护现场,一般只需要保护{r0-r3,lr} BL irqHandler ;跳到具体的异常处理函数 LDMFD r13,{r0-r3,pc}^ ;恢复现场 有程序可以看出,通过”SUB R14,R14,#4”计算中断函数的返回地址。那有人一定会问,为什么计算返回地址的时候要减去4呢? | 地址 | 指令 | 0x3000 | BL add | 0x3004 | MOV r0,#0 | 0x3008 | MOV r1,#1 | 0x300C | MOV r2,#2 |
* d) R7 a2 ? y! |- O0 U9 @) ^- G我们看上个表,比如在执行地址为0x3004的move指令时,突然来了一个IRQ中断,这个中断打断了move指令的执行,这个时候就要去跳转到异常处理函数,之后还要返回0x3004地址重新执行move指令。当中断发生时,LR里面保存了用户模式下PC的值,那么当执行地址为0x3004的move指令时,PC的值应该是0x300C,前面介绍过,当发生跳转时,处理器会对LR进行一个自动的更新动作:LR=LR-0x4,这样LR里面的地址是0x300C-0x04=0x3008。但是0x3008并不是我们要的地址,因为中断发生在地址为0x3004的move指令执行的时候,所以中断处理完后应该返回这个地址。 这就是在计算返回地址的时候LR减去4的原因。对于FIQ中断和预取指中止异常,计算返回地址方法和IRQ相同。 ' Q( H: H2 v- W% ?1 v
|