文章目录
    
    
    
    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 版权协议,转载请附上原文出处链接和本声明。