目前,大多数手机的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 :0000 d 11 c http://www.Sina.com/bl _ set _ TLS
. text:00021888 __set_tls
偏移计算:
(21888-D11C - 8 )/4=0x51D9
EB000000 |0x51D9=EB0051D9
D9 51 00 EB
thumb命令都是2字节。 BL看起来像4字节指令,但其实是误解。 因为长跳跃由两个跳跃命令构成。
0-11位表示11位的地址,具体含义如下。
第11位是0,表示从上位的偏移
第11位是1,表示位移的低位
完整命令:
. text 33600002 E3 f2f 7a2edblxnanosleep.text :0002 e3c 638 B1 cbzr 0,loc ret _ 2e3d8. text 3360002 e3c8E6 f 766 F8 bl _ _ errr
. text :00020 f 08 nanosleep.text :00014498 _ errno
首先说BL命令:
002 e3c 8http://www.Sina.com/bl _ errno
00014498 __errno
是怎么获得目标地址的,计算方法如下。
分析偏移
f7e6(11101111100110 )第11位为0,因此表示高位移位
f866(111100001100110 )第11位为1,表示低位偏移
最高位: F7E6后11位7E6
最后一名: F866后11名66
7e 612 (十进制)=7E6000
66 1=CC抄送
7E6000 | CC=7E60CC
计算出7E60CC的最高符号位为1,意味着向前方跳跃,需要-1,然后反转,数值成为fffffff 819 f 34,成为19F34,
2E3C8 4 - 19F34=14498
如果计算出的数字符号位为0,则保持该值不变,然后进行相加而不是减法。
偏移量0xF866F7E6该怎么计算呢? 计算方法如下。
offset=(目标地址-源地址-4)0x007fffff=7E60CC
high=offset 12 (十进制)=7E6
low=(offset0x00000fff )1=66
machinecode=(0xf800|low ) 16 )|)| (0xF000 | high ) ) ) ) ) ) ) ) ) )。
=F8660000 | F7E6=0xF866F7E6
注意F800相当于高偏移量的第11位到第15位,F0000相当于低偏移量的第11位到第15位。
让我们来谈谈BLX命令:
002 e3c 2http://www.Sina.com/blx nanosleep
00020F08 nanosleep
那么,偏移0xEDA2 F7F2是如何得到的呢? 与BL算法略有不同:
offset=(目标地址-发送方地址-4)0x007fffff=7F2B42
high=offset 12=7F2
low=(offset0x00000fff )1=5A1
if(low%2!=0}{
行;
}//low=5A2
machinecode=(0xe800|low ) 16 )|)| (0xF000 | high );
=EDA20000 | F7F2=EDA2 F7F2
thumb:
B:0x17向前跳跃,0x14向后跳跃
BL:0x97向前跳0x94向后跳
偏移地址计算过程:
(目标地址-命令地址(/4=偏移
()负8、根据指令流水。
除了//4之外,命令的长度已经决定,所以不存储地址差,而存储命令的个数差。
完整命令:
. text 3360000000000008 cc 848 db3ff 97 blje _ arena _ malloc _ hard
. text 336000000000000079 ab8je _ arena _ malloc _ hard
偏移计算:
(79AB8-8CC84 )/4=fffffffb 38d
FFB38D |0x97000000=97FFB38D