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保存了函数的其他参数

相关推荐
开发者阿伟2 分钟前
Android Jetpack LiveData源码解析
android·android jetpack
weixin_4381509915 分钟前
广州大彩串口屏安卓/linux触摸屏四路CVBS输入实现同时显示!
android·单片机
CheungChunChiu1 小时前
Android10 rk3399 以太网接入流程分析
android·framework·以太网·eth·net·netd
木头没有瓜1 小时前
ruoyi 请求参数类型不匹配,参数[giftId]要求类型为:‘java.lang.Long‘,但输入值为:‘orderGiftUnionList
android·java·okhttp
键盘侠0072 小时前
springboot 上传图片 转存成webp
android·spring boot·okhttp
江上清风山间明月2 小时前
flutter bottomSheet 控件详解
android·flutter·底部导航·bottomsheet
Crossoads4 小时前
【汇编语言】外中断(一)—— 外中断的魔法:PC机键盘如何触发计算机响应
android·开发语言·数据库·深度学习·机器学习·计算机外设·汇编语言
sunphp开发者5 小时前
黑客攻击网站,篡改首页问题排查修复
android·js
我又来搬代码了5 小时前
【Android Studio】创建新项目遇到的一些问题
android·ide·android studio
ggs_and_ddu9 小时前
Android--java实现手机亮度控制
android·java·智能手机