ARM中使用B,BL指令进行跳转,两者之间的差距在于:BL指令可以实现子程序的返回,B指令无法实现子程序的返回。
B指令机器码:0xEA
BL指令机器码:0xEB
在反汇编之后,如果是大端的话,指令的第一字节为B/BL的机器码;如果是小端的话,指令的第四个字节为B/BL字节码。
A
偏移值计算方式如下:
目的地址为要跳转到的位置,当前地址为B/BL指令所在的地址。
+8的原因是因为ARM架构下,PC值为当前指令地址+8,就是这样设计的。
目的地址相对PC的差是字节数,但是偏移指的是相差的指令数,所以再除以一条指令的字节数(4)。
B
示例:
.text:0000D11C D9 51 00 EB BL __set_tls
.text:00021888 __set_tls
当前地址0000D11C,目的地址00021888,偏移值=(00021888-(0000D11C+8))/4=0x0051D9
这个偏移值在BL指令对应的二进制中也有体现。
C
特殊的:
我反汇编的一个二进制它的要跳转到的目的地址是小于当前指令地址的,所以中间还涉及到补码的问题。
当前地址:0x000241AC
目的地址:0x0000BF40
((当前地址+8)-目的地址)/4=((241AC+8)-BF40)/4=0x609D
因为当前地址大于目的地址,小减大会出现负值,因此这里采用大减小,那么计算出的结果就是偏移值的补码。
在BL指令对应的二进制中,偏移值有3字节,所以使用FF FF FF-60 9D+1=0xFF9F63,小端就是63 9F FF。(或者直接1000000-609D)
D
如果在上例中已知当前指令地址,以及当前指令的二进制(偏移值),那么如何求要跳转的目的地址呢?
根据公式,首先可以知道 目的地址=(当前地址+8)-偏移值补码*4
偏移值补码=1000000-FF9F63=0x609D
目的地址=241AC+8-609D*4=0xBF40,验证正确。
参考链接:
2. arm32和arm64常用指令B BL BLX机器码计算