当中断或异常发生的时候,cpu自动将pc指向一个特定的地址,这个地址就是中断向量表。
在32位arm系统中,一般都是在中断向量表中放置一条分支指令或pc寄存器加载指令,实现程序跳转到中
断服务例程的功能。例如:
irqentry b handleirq ;跳转范围较小
ldr pc,=handlefiq
;ldr伪指令等效生成1条存储读取指令和1条32位常数定义指令。32位常数存储在ldr指令四周的存储单元
中,相对偏移小于4kb。该32位数据就是要跳转到的中断服务程序入口地址。
之所以使用ldr伪指令,是因为arm的risc指令为单字指令,不能装载32位的立即数 (常数),无法直接
把一个32位常数数据或地址数据装载到寄存器中。所以我们一般将中断向量按如下方式设置中断向量表
ldr pc, reset_addr 1
ldr pc, undefined_addr
ldr pc, swi_addr
ldr pc, prefetch_addr
ldr pc, abort_addr
nop ; reserved vector must be remained
ldr pc, irq_addr
ldr pc, fiq_addr
vector_addr_table
reset_addr dcd reset_handler 9
undefined_addr dcd undefinedhandler
swi_addr dcd swihandler
prefetch_addr dcd prefetchaborthandler
abort_addr dcd dataaborthandler
irq_addr dcd irqhandler
fiq_addr dcd fiqhandler
上面中断向量表的第9行就是从地址0x00000020开始分配一个字的空间(也就是4字节),这4个字节的内容就是reset_handler函数的地址0x00001000。reset_addr的值就是这4个字节的首地址0x00000020。
dcd是arm的伪指令。作用是分配一个字的空间。功能类似于c51里定义一个数组并初始化。
unsigned char reset_addr[4]={0x00,0x00,0x10,0x00};
对比一下就明白了。
再分析第1行。ldr只能在当前pc的4kb范围内跳转,b命令只能在当前pc的32mb范围内调转。
reset_handler的地址是0x00001000,已经超出了当前pc的4k范围,所以不能用
ldr pc, reset_handler
这里不好理解,涉及到arm的寻址方式。
ldr rn,语句标号
这种表达式里,是相对寻址,基址是程序计数器pc,偏移量是语句标号到pc处的指令条数。
ldr pc,语句标号只能在当前pc的4kb范围内跳转的原因是这条指令译码后,偏移表达式占用指令代码32位的最后12位,也就是2^12=4kb。
完整的分析下,以复位为例。地址0x00000020开始的4字节内容是复位处理函数reset_handler的地址0x00001000。reset_addr的地址是0x00000020。当产生复位时,pc=0x00000000,跳到第1行语句执行。ldr pc, reset_addr把0x00000020处的一个字的内容送到pc,然后pc跳转到0x00001000处开始执行。
ldr pc, reset_addr是间接寻址,就是把地址reset_addr处的一个字送给pc。
『本文转载自网络,皇冠最新app版本的版权归原作者所有,如有侵权请联系删除』