arm32和arm64常用指令B BL BLX机器码计算

现在大部分手机cpu架构是ARM v7-A和ARMV8-A,,在ARM-v7A中常使用32位ARM指令集并且支持thumb指令集与arm的切换,而在ARMV8中使用的是64位ARM指令集且不再有thumb指令集状态的切换了。在调用函数时,会有常用的调用方式:BL和B,且分三种情况arm, thumb, aarch64,而对于BLX在arm64指令集中不再有。下面对这三种情况进行讨论。


ARM:



常见跳转指令机器码:

B:0xEA

BL:0xEB


偏移地址计算过程:


(目标地址 - 指令地址 - 8)/ 4 = 偏移

// 减8,指令流水造成。

// 除4,因为指令定长,存储指令个数差,而不是地址差。


完整指令:

.text:0000D11C D9 51 00 EB                             BL              __set_tls

.text:00021888                         __set_tls


计算偏移:

(21888-D11C - 8) /4 = 0x51D9

EB000000 | 0x51D9 =  EB0051D9


thumb:



thumb指令都是2字节。BL看起来像四字节指令,其实是个误解,因为长跳转是由两条跳转指令组成的。



0-11位表示11位地址,具体含义如下:

第11位为0,代表偏移高位

第11位为1,代表偏移低位


完整指令:

.text:0002E3C2 F2 F7 A2 ED                             BLX             nanosleep
.text:0002E3C6 38 B1                                   CBZ             R0, locret_2E3D8
.text:0002E3C8 E6 F7 66 F8                             BL              __errno
.text:0002E3CC 01 68                                   LDR             R1, [R0]

.text:00020F08                         nanosleep
.text:00014498                         __errno


先讲BL指令:


0002E3C8 E6 F7 66 F8                             BL              __errno

00014498                         __errno


如何得到目标地址的呢,计算方式如下:


解析偏移

F7E6(1111011111100110) 第11位为0,所以代表高位偏移

F866(1111100001100110)第11位为1,所以代表低位偏移


最高位:F7E6 取后11位 7E6

最低位:F866 取后11位 66

7E6 << 12(十进制) = 7E6000

66  << 1 =  CC

7E6000 | CC = 7E60CC


计算出来7E60CC最高位符号位为1,代表向前跳转,需要-1然后取反,得到数值为FFFFFFFFFF819F34,取19F34,

2E3C8+ 4 - 19F34 = 14498

若计算出来的数符号位为0,则直接保留该值,然后后面相加而不是减。


那偏移0xF866F7E6又该如何计算出来呢,计算方式如下:


offset = (目标地址- 源地址 -4) & 0x007fffff = 7E60CC

high = offset >> 12(十进制) = 7E6

low = ( offset & 0x00000fff )>>1  = 66


machineCode = ((0xF800 | low) << 16) | (0xF000 | high)
=F8660000 | F7E6 = 0xF866F7E6

注意F800相当于高偏移取第11位到第15位, F0000相当于取低偏移第11位到第15位。



再讲BLX指令:


0002E3C2 F2 F7 A2 ED                             BLX             nanosleep

00020F08                         nanosleep


那偏移0xEDA2 F7F2 如何得到的呢,跟BL算法稍微不同:


offset = (目标地址- 源地址 -4) & 0x007fffff = 7F2B42

high = offset >> 12 = 7F2

low = ( offset & 0x00000fff )>>1  = 5A1

if(low % 2 != 0) {

low++;

}//low=5A2


machineCode = ((0xE800 | low) << 16) | (0xF000 | high);
=EDA20000 | F7F2 = EDA2 F7F2


ARM64:



B:0x17向前跳转,0x14向后跳转

BL:0x97向前跳转  0x94向后跳转


偏移地址计算过程:

(目标地址 - 指令地址)/ 4 = 偏移

// 减8,指令流水造成。

// 除4,因为指令定长,存储指令个数差,而不是地址差。


完整指令:

.text:000000000008CC84 8D B3 FF 97                             BL              je_arena_malloc_hard

.text:0000000000079AB8                         je_arena_malloc_hard


计算偏移:

(79AB8-8CC84) / 4 = FFFFFFFFFFFFB38D

FFB38D | 0x97000000 = 97FFB38D

你可能感兴趣的:(android逆向)