arm64汇编指南

寄存器

寄存器是CPU的组成成分, 存放着指令、数据和地址,速度比内存块

分为通用寄存器状态寄存器浮点寄存器

通用寄存器

ARM64有31个通用寄存器, 每个寄存器可以存储64位数据(8个字节)

使用 X0-X30 表示64位的数

使用 W0-W30 时,访问这些寄存器的低32位, 会将高32位清0。

  • X0-X7

    传递函数的参数, 如果有更多的参数需要使用栈来传递, X0 用来存储函数的返回值

  • SP(Stack Pointer)

    栈指针寄存器, 指向栈的顶部, WSP表示栈指针的最低32位

  • FP(Frame Pointer)

    即X29, 栈指针寄存器, 指向栈的底部

  • LR(Link Register)

    X30 链接寄存器, 存储着函数调用完成时的返回地址

    用来存储函数调用栈跟踪, 程序在崩溃时能够将函数调用栈打印就是借助LR寄存器来实现的

  • PC(Program Counter)

    保存下一条指令的内存地址, 通常在调试状态下看到的 PC 值都是当前断点处的地址

状态寄存器(CPSR)

保存指令运行结果的信息

根据运算的结果来设置状态寄存器的标志位

CPU内部进行置位, 不能用程序赋值

28-31位(最后四位 0011 == 6)分别代表 V C Z N

  • N(Negative)

    符号整数进行运算时, N=1表示结果为负数, N=0表示结果>=0

  • Z(Zero)

    Z=1表示运算结果为0, Z=0表示结果为非0

  • C(Carry)

    加减法运算是否产生进位

  • V(Overflow)

    加减法运算时产生符号位溢出

浮点寄存器(FPU)

用于浮点数存储和运算, V0-V31

常用指令

算法指令

  • ADD 加

    ADD X0,X1,X2: X0=X1+X2

  • SUB 减

    SUB X0,X1,X2: X0==X1-X2

  • MUL 乘

    MUL X0,X1,X2: X0=X1*X2

  • SDIV 有符号数除法运算

    SDIV X0,X1,X2: X0=X1/X2

  • UDIV 无符号

  • CMP X28,X0

    X28,X0相减,更新CPSR中条件标志位

  • CMN CMN X28,X0

    X28,X0相加,更新CPSR中条件标志位

  • ADDS/SUBS

    S的指令运算结果会影响 CPSR中的条件标志位

条件跳转

  • B.cond

    B.cond label 若cond为真,则跳转到 label

  • CBNZ

    CBNZ Xn,label 若Xn!=0,则跳转到label

  • CBZ

    CBZ Xn,label 若Xn==0, 则跳转到label

无条件跳转

  • B

    B label 无条件跳转

  • BL

    BL label 无条件跳转,返回地址保存到LR寄存器中

  • BLR

    BLR Xn 无条件跳转到Xn寄存器的地址,返回地址保存到LR寄存器中

  • BR

    BR Xn 无条件跳转到Xn寄存器的地址

  • RET

    返回到LR中存储地址

逻辑指令

  • AND

    AND X0,X1,X2: X0=X1&X2

  • EOR

    X0=X1^X2

  • ORR

    X0=X1|X2

赋值指令

MOV

MOV X19,X1 X19=X1

地址偏移

ADR

ADR Xn,label Xn=PC+label

Load/Store指令

LDR Xn,addr Load

内存地址addr -> Xn

STR Xn,addr

Xn -> 内存地址addr

LDP Xn1,Xn2,addr

内存地址addr -> Xn1和Xn2

P(Pair)表示一对,同时操作两个寄存器

STP Xn1,Xn2,addr

Xn1和Xn2 -> addr

LDUR Xn,[base, #XXX]

addr(base+#XXX) -> Xn

STUR Xn,[base, #XXX]

Xn -> base+#XXX的内存地址

扩展含义

B 无符号8bit

SB 有符号8bit

H: 无符号116bit

SH 有符号16位

W 无符号32位

SW 有符号32位

函数调用汇编

定义一个最简单的函数调用

csharp 复制代码
int addTwoValue(int a, int b) {
    return a + b;
}

int main() {
    return addTwoValue(1, 2);
}

查看汇编源码

main 函数

ini 复制代码
ZZDemo`main:
    0x1027ba1e8 <+0>:  sub    sp, sp, #0x20 ; 开辟0x30大小的栈空间
    0x1027ba1ec <+4>:  stp    x29, x30, [sp, #0x10] ;保存当前函数的x29(FP)和X30(LR)到栈中
    0x1027ba1f0 <+8>:  add    x29, sp, #0x10 ; 抬高栈底,切换到子函数栈空间
    0x1027ba1f4 <+12>: stur   wzr, [x29, #-0x4]
    0x1027ba1f8 <+16>: mov    w0, #0x1 ; 第一个参数1保存到w0
    0x1027ba1fc <+20>: mov    w1, #0x2 ; 第二个参数2保存到w1
->  0x1027ba200 <+24>: bl     0x1027ba1c8  ;调用 addTwoValue函数
    0x1027ba204 <+28>: ldp    x29, x30, [sp, #0x10] ;从栈中恢复当前函数的x29(FP)和X30(LR)
    0x1027ba208 <+32>: add    sp, sp, #0x20 ; 回收栈空间
    0x1027ba20c <+36>: ret  
csharp 复制代码
ZZDemo`addTwoValue:
    0x100c3e1a8 <+0>:  sub    sp, sp, #0x10
    0x100c3e1ac <+4>:  str    w0, [sp, #0xc]
    0x100c3e1b0 <+8>:  str    w1, [sp, #0x8]
->  0x100c3e1b4 <+12>: ldr    w8, [sp, #0xc]
    0x100c3e1b8 <+16>: ldr    w9, [sp, #0x8]
    0x100c3e1bc <+20>: add    w0, w8, w9
    0x100c3e1c0 <+24>: add    sp, sp, #0x10
    0x100c3e1c4 <+28>: ret    

一般函数执行流程如下

  1. 分配栈空间
  2. 如果有子函数调用, 保存当前函数的形参到栈中
  3. 如果有子函数调用, 保存当前函数的FP和LR
  4. 抬高栈底, 切换到子函数栈
  5. 设置子函数的实参
  6. 调用子函数,返回结果
  7. 恢复当前函数形参
  8. 恢复当前函数的FP和LR
  9. 其他操作
  10. 回收栈空间
  11. 返回

Objective-C汇编

OC中方法调用是通过消息机制来实现的

objectivec 复制代码
@implementation AppDelegate

- (void)printValue1:(NSString*)value1 value2:(NSString*)value2 {
    NSLog(@"%@, %@", value1, value2);
}

@end

int main() {
    AppDelegate *delegate = [[AppDelegate alloc] init];
    [delegate printValue1:@"111" value2:@"222"];
}

断点到函数处执行

ini 复制代码
register read

        x0 = 0x000000028261c0e0
        x1 = 0x00000001040d3109  "printValue1:value2:"
        x2 = 0x00000001040d4070  @"111"
        x3 = 0x00000001040d4090  @"222"
        x4 = 0x0000000000000004
        x5 = 0x0000000007600000
        x6 = 0x0000000000000000
        x7 = 0x0000000000000000

po $x0

<AppDelegate: 0x28261c0e0>

在 OC 中

x0 寄存器保存了对象本身

x1保存了方法名,

x2-x7保存了函数的其他参数

相关推荐
rocpp11 小时前
Android 相册选择与拍照接入实践:MediaStore 分页、权限适配与 FileProvider
android
Flynt12 小时前
升级Flutter 3.44,我踩了HCPP和AGP 9的坑
android·flutter·dart
白色牙膏12 小时前
Cocos Creator 2.4.x 接入 AdMob 插件的迁移实践
android
我命由我1234514 小时前
C++ - 面向对象 - 常成员函数
android·java·linux·c语言·开发语言·c++·算法
tryqaaa_15 小时前
学习日志(四)【php反序列化魔术方法以及pop构造配实战】
android
Java小学生丶16 小时前
记录一下我的 Gradle 开发环境配置过程
android·java·gradle·maven·安卓
问心无愧051317 小时前
ctf show web 入门256
android·前端·笔记
霸道流氓气质17 小时前
MySQL 索引设计实战指南
android·数据库·mysql
R语言爱好者17 小时前
叠氮酸介绍
android
方白羽17 小时前
Android WebView 中实现第三方 QQ 登录的架构与流程详解
android·app