arm汇编的跳转指令无非是b和ldr。但是如果没有足够理解,别人灵活的用一下你就犯晕了。
首先我们要知道两者的两个本质区别:
1、b是位置无关的,ldr不是位置无关的。
2、b的范围只能是+—32MB,而ldr是4GB。
在arm的启动汇编的中断向量表是必然用跳转指令的,但是就是这里也有很多实现形式:
方式1:
B InitReset ; 0x00 Reset handler
undefvec:
B undefvec ; 0x04 Undefined Instruction
swivec:
B swivec ; 0x08 Software Interrupt
pabtvec:
B pabtvec ; 0x0C Prefetch Abort
dabtvec:
B dabtvec ; 0x10 Data Abort
rsvdvec:
B rsvdvec ; 0x14 reserved
irqvec:
B IRQ_Handler_Entry ; 0x18 IRQ
这个我很容易理解,实现的标号油InitReset和IRQ_Handler_Entry,其他没有实现的在原地跳转。
方式二:
LDR pc, =resetHandler ; Reset
LDR pc, Undefined_Addr ; Undefined instructions
LDR pc, SWI_Addr ; Software interrupt (SWI/SYS)
LDR pc, Prefetch_Addr ; Prefetch abort
LDR pc, Abort_Addr ; Data abort
B . ; RESERVED
LDR pc, =irqHandler ; IRQ
LDR pc, FIQ_Addr ; FIQ
LDR PC,[PC,#0x18]
Undefined_Addr: DCD Undefined_Handler
SWI_Addr: DCD SWI_Handler
Prefetch_Addr: DCD Prefetch_Handler
Abort_Addr: DCD Abort_Handler
FIQ_Addr: DCD FIQ_Handler
我们注意到两种ldr
一种LDR PC,=label,这时把LDR当做伪指令,他要被翻译成:
LDR PC,[PC,offset_to_label2]
label2:DCD resetHandler
这种label是在程序中标记的了,如resetHandler和irqHandler
还有一种LDR PC,label,这时直接把label地址内存内容copy到PC中
这种label都是 label:DCD label2 ,这些label2可以在任何地方实现
我们来理解b和ldr两者的不同
1,b是位置无关,因为他的跳转都是相对PC来的,而ldr不是位置无关的,因为他的跳转是根据DCD里面的值,这个值是连接的时候确定的,他是跟连接地址有关的
2,b的范围只能是32M,是因为指令里面给偏移的空间只有24bit,而ldr是一个32bit的DCD,所以他是32bit的
注意:像上面方式二
LDR pc, =resetHandler ; Reset
。
。
。
resetHandler:
....
....
如果运行地址是0,那么LDR pc, =resetHandler还在以基址为0的空间运行
但是执行完了,假设装载地址是0x3000000,所以resetHandler的基址不是0,而是0x30000000
所以resetHandler标号以后的指令应该存在以0x3000000为基址的空间,pc跳过去了
这种技巧在at91的remap模式经常用到
阅读(1723) | 评论(0) | 转发(0) |