android study 3

Author Avatar
Xzhah 5月 22, 2022
  • 在其它设备中阅读本文章

Android知识学习

1.ARM汇编指令

​ 之前打交道比较多的是x86指令集,接触过一点Mips指令集,对于arm指令集还没系统学习过

1.1 arm的运行状态

​ arm分为七种运行模式和两种运行状态。

​ 运行模式即用户模式(类似windows的ring3程序),系统模式(类似ring0),…等

​ 运行状态分为ARM和Thumb状态。

1.1.a. Thumb状态

​ Thumb状态是2字节,可以看做是ARM指令压缩形式的子集,具有16位的代码密度(也就是2个字节指令长度),但是只能是支持通用功能,必要的时候仍然需要ARM 指令。

1.2 arm寄存器

​ arm寄存器一共有37个,其中31个通用的,6个是状态寄存器。其中31个中分为未分组寄存器和分组寄存器。

未分组寄存器

​ 1.R0-R7,其意义是在各种运行模式下都可以使用的通用寄存器。R0-R7是通用寄存器,其中R0-R3可以用来传递参数,返回值。如果传参的时候寄存器不够的话就使用压栈来完成了。结果返回的寄存器是R0。

分组寄存器

​ 1.分组寄存器也就是说在不同模式下,会有不同的寄存器,R8-R12是较为特殊的,因为只有在快速模式(FIQ)下,其名字才不一样。也是通用寄存器,可以用来存局部变量之类的。

​ 2. R11寄存器,代表栈底指针。

​ 3.R13寄存器,代表sp栈顶指针。

​ 4.R14寄存器,也叫LR寄存器,即链接寄存器,可以用作保存子程序或者中断的返回地址。

​ 5.R15寄存器,PC寄存器,类似于EIP。

​ 6.CPSR状态寄存器,类似于EFLAGS寄存器。其中的第五位为1时则代表运行在ARM状态,如果T=0则代表运行在Thumb状态。

1.3 arm 64寄存器

​ 本质上没有什么不同,详情可以见https://support.huaweicloud.com/ref-kunpenggrf/kunpenggrffaq_10_0057.html

​ 比较有意思的是X16,X17寄存器

​ x16~x17是Intra-procedure-call scratch registers。也就是调用的函数里会用到的一些寄存器(又叫IP0,IP1),比如常用于动态链接中的plt寻址等指令。比如以下指令:

1
2
3
4
	1. adrp  x16, 11000 <func22+0x10b30> #adrp会拿到目标地址所在页的基址,这里应该就是相应的got表地址了
2. ldr x17, [x16]
3. add x16, x16,
4. br x17

2.调用约定

2.1 arm/arm64调用约定

​ ARM和ARM64使用的是ATPCS(ARM-Thumb Procedure Call Standard/ARM-Thumb过程调用标准)的函数调用约定。

​ ARM会把参数保存到R0-R3寄存器中,剩下的参数从右到左压栈。返回值放在R0中。

​ ARM64则是参数保存至X0-X7寄存器中,上下的参数从右到左入栈,返回值放在X0中。

2.2 x86调用约定

​ 顺便说一下x86的调用约定,x86可以分为三种调用约定: cdecl/stdcall/fastcall。cdecl/stdcall是直接压栈,参数从右往左依次入栈,返回值放在EAX寄存器中。fastcall则是参数1,2保存在ECX,EDX中,剩下的参数从右往左依次入栈。结果放在EAX寄存器中。

​ x64则只有fastcall一种调用约定,参数1,2,3,4保存至RCX,RDX,R8,R9中,剩下参数从右往左依次入栈。

2.3 C++函数调用约定

​ 西加加是遵循thiscall函数调用约定,对于x86,会把this指针存入ECX。x64则是参数1,2,3存在RDX,R8,R9,this指针存入ECX。

​ 对于ARM而言,则是把this指针存在R0中,参数1,2,3存在R1,R2,R3。ARM64则是this指针存在X0中,参数1-7存放在X0-X7中,剩下参数从右到左入栈。

3.跳转指令

​ ARM的跳转指令有B,BL,BX,BLX。

​ 1.跳转指令B就是无条件跳转,类似于jmp指令。用法: B label

​ 2.BL指令则是带返回的跳转指令,跳转之前会在R14(LR寄存器)中存入当前PC的值。类似于call指令。用法: BL label

​ 3.BX则是带状态切换的跳转指令,根据operand的最低位来判断,如果是1则是Thumb状态,如果是0则是ARM状态。用法:BX 寄存器

​ 4.BLX则是带返回和状态切换的,如果用法是BLX label,则一定会更改处理器的状态。如果是BLX 寄存器,则根据其在最低为来决定。

​ 还有BNE,BEQ这些根据状态寄存器的条件跳转指令。。。除了跳转指令之外,还可以通过MOV,LDR指令,把地址直接赋给PC寄存器从而实现跳转。如MOV PC, LR。或者LDR PC,=0xFFFFFFFF(加等号表示是伪指令,直接把0xFFFFFFFF赋值给PC,否则是去该地址上取值)