文章目录
1. iOS汇编
1.1 arm64汇编和x86汇编
-
真机: arm64汇编
- 寄存器
- 指令
- 堆栈
- 模拟器: x86汇编
1.2 如何用汇编写一个函数?
-
首先创建一个头文件.h和一个实现文件.s(大多数的汇编文件以.s结尾)
2. 指令
2.1 mov
mov x0, #0x8
2.2 ret
- 函数返回
-
将
lr (x30)
寄存器的值赋值给pc寄存器
2.3 add
_add:
mov x0, #0x1
mov x1, #0x2
add x2, x0, x1
ret
2.4 sub指令
-
sub指令的格式为:
_sub:
mov x0, #0x3
mov x1, #0x2
sub x2, x0, x1
ret
2.5 cmp
- 将2个寄存器相减
-
相减的结果会影响cpsr寄存器的标志位
_add:
mov x0, #0x3
mov x1, #0x2
cmp x0, x1
bgt mycode
mov x2, #0x5
mycode:
mov x2, #0x6
ret
2.6 跳转指令b 和 bl
2.6.1 b
- 跳转指令
- 可以带条件跳转,一般跟cmp配合使用
2.6.2 bl
- 带返回的跳转指令
-
执行的操作
-
将下一条指令的地址存储到
lr (x30)
寄存器中 - 跳转到标记处开始执行代码
-
将下一条指令的地址存储到
2.6.3 b 和 bl 指令的区别
- 就是b不带返回, 即使有ret 也不会返回
- bl 会带返回, 执行完跳转指令, 立马返回到下一条指令
2.7 条件域
- EQ: equal,相等
- NE: not equal,不相等
- GT: great than,大于
- GE: greate equal, 大于等于
- LT: less than,小于
-
LE: less equal, 小于等于
2.8 内存操作
-
load, 从内存中读取数据
- Idr、Idur(用来接收负数的)
-
ldp (p是pair的简称)
; ldr指令
ldr x0, [x1]; // 从`x1`指向的地址里面取出一个 64 位大小的数存入 `x0`
; ldp 指令
ldp x1, x2, [x10, #0x10]; // 从 x10 + 0x10 指向的地址里面取出 2个 64位的数,分别存入x1, x2
-
store, 往内存中写入数据
- str、stur(用来计算负数的)
-
stp : 从内存中读取数据, 放到一对寄存器中
; str指令
str x5, [sp, #24]; // 把x5的值(64位数值)存到 sp+24 指向的内存地址上
; stp 指令
stp x29, x30, [sp, #-16]!; // 把 x29, x30的值存到 sp-16的地址上.
ldp x29, x30, [sp], #16; // 从sp地址取出 16 byte数据,分别存入x29, x30. 然后 sp+=16;
2.9 指令列表
3. 寄存器
3.1 通用寄存器
- 64bit的: x0~x28
- 32bit的: w0~ w28 (属于x0 ~ x28的低32bit)
- x0~x7通常拿来存放函数的参数,更多的参数使用堆栈来传递
- x0通常拿来存放函数的返回值
- 通过LLDB可以查看所有的寄存器(register)
register read
3.2 程序计数器
- pc (Program Counter)
- 记录CPU当前指令的是哪一条指令
- 存储着当前CPU正在执行的指令的地址
- 类似于8086汇编的ip寄存器
3.3 堆栈指针
- sp (Stack Pointer)
- fp (Frame Pointer) ,也就是x29
3.4 链接寄存器
- lr (Link Register) ,也就是x30
- 存储着函数的返回地址
3.5 程序状态寄存器
- cpsr (Current Program Status Register)
-
spsr (Saved Program Status Register) ,异常状态下使用
3.6 零寄存器,里面存储的值是0
- wzr (32bit, Word Zero Register)
- xzr (64bit)
4. 寻址方式
- 总结:
[x10, #0x10] // signed offset。 意思是从 x10 + 0x10的地址取值
[sp, #-16]! // pre-index。 意思是从 sp-16地址取值,取值完后在把 sp-16 writeback 回 sp
[sp], #16 // post-index。 意思是从 sp 地址取值,取值完后在把 sp+16 writeback 回 sp
常用LLDB的汇编指令
- 查看单个寄存器的值
register read x0
- 读取所有寄存器的值
register read
- 给某个寄存器写入值
register write 寄存器 值
- 查看内存地址的内容
x 地址
-
打印方法相关
- po $x0 :打印方法调用者
- x/s $x1 :打印方法名及地址
- po $x2 :打印参数(以此类推, x3、x4也可能是参数)
- 如果是非arm64 ,寄存器就是r0、r1、 r2
生成汇编文件
- main.s 可写可不写, 默认生成main.s文件
xcrun --sdk iphoneos clang -S -arch arm64 main.c -o main.s
版权声明:本文为zhongad007原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。