09-1-ARM64汇编之基础

  • Post author:
  • Post category:其他




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