|
寄存器
汇编指令栈栗子
逆向工程绕不过的一部分就是汇编指令的分析。我们iPhone里面用到的是ARM汇编,但是不同的设备也有差异,因CPU的架构不同。
| 架构 |
设备 |
| armv6 |
iPhone, iPhone2, iPhone3G, 第一代、第二代 iPod Touch |
| armv7 |
iPhone3GS, iPhone4, iPhone4S,iPad, iPad2, iPad3(The New iPad), iPad mini, iPod Touch 3G, iPod Touch4 |
| armv7s |
iPhone5, iPhone5C, iPad4(iPad with Retina Display) |
| arm64 |
iPhone5S 及以后版本 |
从iPhone5s之后的苹果手机都是ARM64位操作系统了,所以我们直接从ARM64汇编指令开始。
寄存器
我们都知道CPU的典型构成中有寄存器、控制器和运算器等组成,部件之间通过总线连接。运算器负责信息处理,控制器负责控制其他期间进行工作,寄存器用于信息存储。对我们程序员来说寄存器是最主要部件,可以通过改变寄存器的内容来实现对CPU的控制。
不同的CPU,寄存器的个数和结构不相同。像8086CPU有14个寄存器。ARM64 有34个寄存器,包括31个通用寄存器、SP、PC、CPSR。
| 寄存器 |
位数 |
描述 |
| X0-X30 |
64bit |
通用寄存器,如果有需要可以当做32bit使用:WO-W30 |
| FP(x29) |
64bit |
保存栈帧地址(栈底指针) |
| LR (X30) |
64bit |
通常称X30为程序链接寄存器,保存跳转返回信息地址 |
| SP |
64bit |
保存栈指针 |
| PC |
64bit |
程序计数器,俗称PC指针,总是指向即将要执行的下一条指令 |
X0-X7: 用于子程序调用时的参数传递,X0还用于返回值传递
X8: 间接寻址结果
LR: 保存子程序结束后需要执行的下一条指令
Xcode在真机中运行项目,然后在viewWillAppear添加断点,lldb中查看各寄存器状态register read
汇编指令
下面介绍ARM64经常用到的汇编指令
MOVX1,X0 ;将寄存器X0的值传送到寄存器X1ADDX0,X1,X2 ;寄存器X1和X2的值相加后传送到X0SUBX0,X1,X2 ;寄存器X1和X2的值相减后传送到X0ANDX0,X0,#0xF ; X0的值与0xF相位与后的值传送到X0ORRX0,X0,#9 ; X0的值与9相位与后的值传送到X0EORX0,X0,#0xF ; X0的值与0xF相异或后的值传送到X0LDRX5,[X6,#0x08] ;X6寄存器加0x08的和的地址值内的数据传送到X5STRX0, [SP, #0x8] ;X0寄存器的数据传送到SP+0x8地址值指向的存储空间STPx29, x30, [sp, #0x10] ;入栈指令
LDPx29, x30, [sp, #0x10] ;出栈指令CBZ;比较(Compare),如果结果为零(Zero)就转移(只能跳到后面的指令)CBNZ;比较,如果结果非零(Non Zero)就转移(只能跳到后面的指令)CMP;比较指令,相当于SUBS,影响程序状态寄存器CPSR B/BL ;绝对跳转#imm, 返回地址保存到LR(X30)RET;子程序返回指令,返回地址默认保存在LR(X30)
NZCV是状态寄存器中存的几个状态值,分别代表运算过程中产生的状态,其中:
-
N, negative condition flag,一般代表运算结果是负数
-
Z, zero condition flag, 运算结果为0
-
C, carry condition flag, 无符号运算有溢出时,C=1。
-
V, oVerflow condition flag 有符号运算有溢出时,V=1。
栈
栈就是指令执行时存放临时变量的内存空间,具有特殊的访问方式:后进先出, Last In Out Firt。
栗子
下面我们写一个简单求和的子函数调用,看看编译成ARM64汇编指令是什么样子的。
#include<stdio.h> intmySum(inta,intb) { intc=a+b; returnc; } intmain(intargc, char*argv[]) {intoutA=10; intoutB=20; intresult=mySum(10,20
); printf("%d",result); return0; }
|