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,驗證正確。
參考鏈接:
