因此,当编译地址(加载地址)和运⾏地址相同时,绝对跳转和相对跳转都可以正确执⾏。⽐如,程序在NORFLASH存储时。但是,当编译地址(加载地址)和运⾏地址不相同时,相对跳转都就会出现问题。⽐如,代码存储在NANDFLASH,由于NANDFLASH并不能运⾏代码,所以需要重定位代码到内部的SRAM。关于NANDFLASH和NORFLASH可以看这篇⽂章S3C2440从NAND Flash启动和NOR FLASH启动的问题。
B(BL)和LDR指令具体怎么执⾏的?
我们以下图中的这句跳转代码分析下指令具体的执⾏过程。
#ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit#endif
上述代码对应的反汇编代码如下:
33f000ac: eb000017 bl 33f00110
33f00110 :33f00110: e3a00000 mov r0, #0 ; 0x033f00114: ee070f17 mcr 15, 0, r0, cr7, cr7, {0}
当指令执⾏到33f000ac时,对应的机器码为eb000017(1110 1011 0000 0000 0000 0000 0001 0111),
其中[31,28]⾼四位为条件码,1110表⽰⽆条件执⾏。[25,27]位保留区域,24位表⽰是否带有返回值,1表⽰带有返回值,也就是BL指令。[23,0]为指令的操作数,0000 0000 0000 0000 0001 0111。按照如下计算⽅式:
1、将指令中24位带符号的补码⽴即数扩展为32位(扩展其符号位)原数变成 0000 0000 0000 0000 0000 0000 0001 0111。
2、将此数左移两位0000 0000 0000 0000 0000 0010 1000 0000 变成 0000 0000 0000 0000 0000 0000 0101
1100 = 0x0000005c
3、将得到的值加到PC寄存器中得到⽬标地址,由于ARM为3级流⽔线,此时的 pc = 33f000ac+8 = 33F000B4,pc =
33F000B4 + 0x0000005c = 33F00110与图中的cpu_init_crit的地址相等。
在算的过程中我们使⽤的始终是PC的值,假设程序在 0 地址处执⾏,那么计算⽅法⼀样,pc 的值变了计算出来的结果也随之改变。所以 BL 的跳转时与位置⽆关的。
下图为B(BL)指令的格式 28~31bts(cond)是条件码,就是表明这条语句⾥是否有⼤于、等于、⾮零等的条件判断,这4bts共有16种状态,分别为:
下图为LDR指令的格式
我们以下图中的第⼀句话作为例⼦分析下汇编语言跳转指令
下图为B(BL)指令的格式
[23,0]bits存放的是要跳转的相对地址,由于指令所在地址必须是4字节对齐的,因此跳转的地址最低bits必然是0,因此BL指令[23,0]bits 保存的是省略这最低2bts的地址,如果补全了这2bits,BL指令就可以表⽰26bits的跳转地址。在这26bits中需要使⽤1bit表⽰向前跳还是向后跳,那么剩下的25bits就可以表⽰32 MBts的范围了,225=32M因此,B(BL)指令的跳转范围为-32MBytes~+32MBytes。
下图为LDR指令的格式
似,其中Rn和Address_mode共同构成第⼆个操作数的内存地址,由Address_mode的9种格式可以直到,Address_mode表⽰的就是偏
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论