2015-2-11
自己写了个IRQ的跳转处理,但是却发现BL指令编译通不过,BLX也不行。
后来才知道,S3C2440还是ARMv4的汇编指令体系结构,不支持BLX,而BL只支持跳转到常量地址。
形如BL R0的写法是不行的,而BX是可以的,BX是带模式切换的,不过模式不需要切换也一样可以用,但BX不能把下一个地址保存到LR中,
只有BL和BLX才可以,所以这里就需要自己保存下一个地址到LR中,这个倒不难。
MOV LR,PC就可以了,不过注意ARMv4虽然是三级流水线,在执行MOV LR,PC时,PC已经指向下两个地址,但也可能不是。
具体要看芯片实现,不过好的是,MOV LR,PC 在具体芯片上偏移多少是固定好了的,所以只要事先测试下知道是多少就好处理了。
这个知识点可以参考杜春雷的《ARM体系结构与编程》,也给出了测试代码,不过因为我手上有仿真器,加断点到MOV LR,PC这一条上,看看PC是多少就知道了,不用写测试代码了。
汇编代码如下:
IRQ_Handler STMFD SP!, {R0-R4, LR} LDR R1,=INTOFFSET LDR R0,[R1] LDR R2,=IRQHandle LDR R3,[R2,R0,LSL #2] MOV LR,PC BX R3 ; BL StartHandle LDMFD SP!, {R0-R4, LR} SUBS PC, LR, #4
跳转到C函数中,用下标查表的方法也可以,思想和汇编代码一样,只是用C写更简单更容易理解,不过这样效率稍稍低了点。
下面是C函数下的反汇编代码:
;;;7 extern void StartHandle(void) 000000 e92d4010 PUSH {r4,lr} ;;;8 { ;;;9 (IRQHandle[S3C_VIC -> INTOFFSET])(); 000004 e3a0144a MOV r1,#0x4a000000 000008 e5911014 LDR r1,[r1,#0x14] 00000c e59f2048 LDR r2,|L1.92| 000010 e7920101 LDR r0,[r2,r1,LSL #2] 000014 e1a0e00f MOV lr,pc 000018 e12fff10 BX r0 ;;;10 } 00001c e8bd4010 POP {r4,lr} 000020 e12fff1e BX lr ;;;11 ENDP
时间: 2024-10-21 14:13:50