• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

arm64汇编指南

武飞扬头像
Bowen_J
帮助1

寄存器

寄存器是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位

函数调用汇编

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

int addTwoValue(int a, int b) {
    return a   b;
}

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

查看汇编源码

main 函数

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  
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中方法调用是通过消息机制来实现的

@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"];
}

断点到函数处执行

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

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgecgeg
系列文章
更多 icon
同类精品
更多 icon
继续加载