前言
日常的应用开发中,主要用的语言是Objective(Swift),一些特殊场景下,可能还会用到C/C++,JavaScript,Shell,Python等。
那么,一个iOS开发者为什么要了解汇编这么底层的语言呢?
因为看得懂汇编能够提高的代码调试和逆向能力。
本文是作者学习汇编过程中整理的笔记,分为上下两篇:上篇主要是一些基础准备,下篇介绍Objective C汇编和一些逆向的Demo。
命令行
Objective C源文件(.m)的编译器是Clang + LLVM,Swift源文件的编译器是swift + LLVM。
所以借助clang命令,我们可以查看一个.c或者.m源文件的汇编结果
clang -S Demo.m
这是是x86架构的汇编,对于ARM64我们可以借助xcrun
,
xcrun --sdk iphoneos clang -S -arch arm64 Demo.m
本文所有的汇编都是基于ARM64架构CPU的
汇编是什么?
汇编语言是一种低级编程语言,不同于Objective C这类高级语言,汇编语言是直接操作硬件(CPU,寄存器,内存等)的。
汇编语言仍然不是最低级的语言,CPU不能直接执行,需要通过汇编器转换成机器语言(0101)才能执行。
汇编语言由汇编指令组成,每一个汇编指令都是直接操作CPU去进行一系列操作。一个典型的汇编语句:
//把整数0存储到寄存器x0
mov x0, #0
寄存器
ARM的全称是Advanced RISC Machine,翻译过来是高级精简指令集机器。
iOS设备CPU架构都是基于ARM的,比如你多少都听过这样的名词:arm64,arm7…它们指的都是CPU指令集。iPhone 5s及以后的iOS设备的CPU都是ARM 64架构的。
ARM64常见的的通用寄存器31个64bit,命名为x0-x30,作用:
寄存器 | 特殊用途 | 作用 |
---|---|---|
SP | Stack Pointer | |
x30 | LR | Link Register |
x29 | FP | Frame Pointer |
x19…x28 | Callee-saved registers | |
x18 | 平台保留寄存器,应用不可以使用。 | |
x17 | IP1 | The second intra-procedure-call temporary register (can be used by call veneers and PLT code); at other times may be used as a temporary register. |
x16 | IP0 | The first intra-procedure-call scratch register (can be used by call veneers and PLT code); at other times may be used as a temporary register. |
x9…r15 | Temporary registers | |
x8 | 间接返回值寄存器,在一些特殊情况下,函数的返回值是通过x8返回的。 | |
x0…x7 | 用来参数传递给子程序或者从函数中返回值,也可以用来存储中间值 |
x系列寄存器是64位的,只用低32bit的时候,称做w0~w30。
- SP(Stack Pointer), 可以把栈理解为存储数据的容器,而Stack Pointer告诉你这个容器有多高,你可以通过移动Stack Pointer来增加/减少你的容器容量。
- LR(Link Register,x30), 在子程序调用的时候保存下一个要执行指令的内存地址。
- FP(Frame Pointer,x29), 保存函数栈的基地址。
除此之外,还有几个特殊的寄存器
- PC寄存器保存下一条将要执行的指令的地址,正常情况下PC指令加1,顺序执行下一跳指令,PC按条件执行指令(比如依次执行指令1,指令5,指令3),是条件分支(比如if/while)的理论基础。
- FLAGS程序状态寄存器,保存若干flags,数据处理的指令会修改这些状态,条件分支指令会读取flag,决定跳转。
- XZR,和WZR 代表零寄存器。
浮点数
由于浮点数运算的特殊性,arm 64还有31个浮点数寄存器q0~q31,长度不同称谓也不同,b,h,s,d,q,分别代表byte(8位),half(16位),single(32位),double(64位),quad(128位)。
Hello world
和任何教程一样, 先看看汇编最简单的汇编代码。新建一个helloworld.c:
#include <stdio.h>
int main()
{
printf("hello, world\n");
return 0;
}
然后,生成汇编文件: