B和BL指令都是相对跳转指令,反汇编虽然给出了“b 33f80050”,但实际上,执行的机器指令为“ea000012 ”,反汇编程序将“ea000012 ”与当前预定的PC的值相结合,计算得出“b 33f80050”。
[31:28]位是条件码;[27:24]位为“1010”时,表示B跳转指令,为“1011”时,表示BL跳转指令;[23:0]表示偏移地址。正确的跳转地址为:
(1)偏移地址扩展为32位数:机器指令“ea000012 ”中表示跳转位置的为:0x000012,将其扩展为32位数,为0x00000012;
(2)将该32位数左移两位,得到真正的基于PC的偏移地址:0x00000012--->0x00000048;
(3)将该偏移地址与当前PC的值相加,得到真正的跳转地址:反汇编程序以ELF格式的文件为输入,该文件中记录了链接脚本中设定的起始地址(默认为0),由于ELF格式中关于该跳转指令的信息只有“ea000012”,不存在像“start_code”这样的标号(链接后丢弃掉了),反汇编程序在执行反汇编过程的时候,只能根据预定的起始地址计算出当前的PC,加上基于PC的偏移地址得到“b 33f80050”,在题主给出的例子中,当前正在执行的指令以预定起始地址为基准的位置为33f80000,而arm为三级流水线构架,所以PC=33f80000+8,所以跳转地址为33f80000+8+00000048=33F80050,和“b 33f80050”一致。
总结来说:B和BL指令确实是以当前PC为基准进行的相对跳转,反汇编得到的跳转地址是基于ELF文件中保留的信息计算出来的地址,而并非运行时真正的跳转地址,当运行起始地址和链接脚本设定的起始地址一致时,两者相等。
也就是说,忘记反汇编出来的那条跳转指令吧。