ARM:
常见跳转指令机器码:
B:0xEA
BL:0xEB
偏移地址计算过程:
(目标地址 - 指令地址 - 8)/ 4 = 偏移
// 减8,指令流水造成。
// 除4,因为指令定长,存储指令个数差,而不是地址差。
完整指令:
假设上一步得到的偏移为0x00000C
跳转指令为:B
则完整指令为:0C 00 00 EA
THUMB:
Thumb指令都是2字节。BL看起来像4字节指令,其实是一个误解,因为长跳转是由两条跳转指令组成的。
0~11位表示11位地址,具体含义如下:
第11位为0,偏移高位(off0)
第11位为1,偏移低位(off1)
例子:
1.向后跳转
0012 00F001F8 bl .Lhelo .Lhelo: 0018 05F0D1F7 pld [r1, r5] |
解析偏移:
取高位 f000, 取后11位 => 000
取低位 f801, 取后11位 => 001
计算偏移:
(000 << 12) | (001 << 1) = 2
由于这个最高位符号位为0,代表向后跳转,只需要保留该值2即可。
目标地址:
0x0012 + 4 + 2 = 0x0018
2.向前跳转
00001164 FF F7 BE FF BL _Z4testv _Z4testv: 000010E4 07 B5 PUSH {R0-R2,LR} |
解析偏移:
取高位 f7ff, 取后11位 => 7ff
取低位 ffbe, 取后11位 => 7be
计算偏移:
(7ff << 12) | (7be << 1) = 7fff7c
由于这个最高位符号位为1,代表向前跳转,需要-1,然后取反,得到值为: ff800084,取84即可。
目标地址:
0x1164 + 4 - 0x84 = 0x10e4