• ARM64常见指令



    ### 📌 栈操作和函数框架设置


    `.text:00000000000038D0                 SUB             SP, SP, #0x30`

    **SUB SP, SP, #0x30**: 为本地变量在堆栈上分配48字节的空间(0x30字节)。

    `.text:00000000000038D4                 STP             X29, X30, [SP,#0x20+var_s0]`

    **STP X29, X30, [SP,#0x20+var_s0]**: 将帧指针(X29)和链接寄存器(X30)以对的形式存储到栈中。


    `.text:00000000000038D8                 ADD             X29, SP, #0x20`

    **ADD X29, SP, #0x20**: 设置新的帧指针,指向当前堆栈指针SP加上0x20的地址。

    ### 📌 加载字符串地址和处理字符


    `.text:00000000000038DC                 ADRL            X8, aAlice ; "Alice"`

    **ADRL X8, aAlice**: 将字符串"Alice"的地址加载到X8寄存器中。

    `.text:00000000000038E4                 LDR             W9, [X8] ; "Alice"`

    **LDR W9, [X8]**: 从X8寄存器指向的内存地址加载一个32位字到W9寄存器。

    `.text:00000000000038E8                 SUB             X1, X29, #-var_8`

    **SUB X1, X29, #-var_8**: 将X29寄存器的值减去-var_8,并将结果存储到X1寄存器。

    `.text:00000000000038EC                 STUR            W9, [X29,#var_8]`

    **STUR W9, [X29,#var_8]**: 将W9寄存器中的值存储到X29寄存器加上var_8偏移地址指向的内存中。

    `.text:00000000000038F0                 LDRH            W8, [X8,#(aAlice+4 - 0x12A3)] ; "e"`

    **LDRH W8, [X8,#(aAlice+4 - 0x12A3)]**: 从X8寄存器加上偏移地址处加载一个半字(16位)到W8寄存器。

    `.text:00000000000038F4                 STURH           W8, [X29,#var_4]`

    **STURH W8, [X29,#var_4]**: 将W8寄存器中的值存储到X29寄存器加上var_4偏移地址指向的内存中。

    `.text:00000000000038F8                 MOV             W8, #0x1E`

    **MOV W8, #0x1E**: 将立即数0x1E加载到W8寄存器中。

    `.text:00000000000038FC                 STUR            W8, [X29,#var_C]`

    **STUR W8, [X29,#var_C]**: 将W8寄存器中的值存储到X29寄存器加上var_C偏移地址指向的内存中。

    ### 📌 浮点操作和内存访问


    `.text:0000000000003900                 MOV             W8, #0x42830000`

    **MOV W8, #0x42830000**: 将立即数0x42830000加载到W8寄存器中。

    `.text:0000000000003904                 FMOV            S0, W8`

    **FMOV S0, W8**: 将W8寄存器中的值移动到S0浮点寄存器中。

    `.text:0000000000003908                 STR             S0, [SP,#0x20+var_10]`

    **STR S0, [SP,#0x20+var_10]**: 将S0寄存器中的值存储到堆栈指针加上var_10偏移地址指向的内存中。

    `.text:000000000000390C                 LDUR            W2, [X29,#var_C]`

    **LDUR W2, [X29,#var_C]**: 从X29寄存器加上var_C偏移地址处加载一个字到W2寄存器。

    `.text:0000000000003910                 LDR             S0, [SP,#0x20+var_10]`

    **LDR S0, [SP,#0x20+var_10]**: 从堆栈指针加上var_10偏移地址处加载一个浮点数到S0寄存器。

    `.text:0000000000003914                 FCVT            D0, S0`

    **FCVT D0, S0**: 将S0寄存器中的单精度浮点数转换为D0寄存器中的双精度浮点数。

    ### 📌 打印和返回


    `.text:0000000000003918                 ADRL            X0, aNameSAgeDWeigh ; "Name = %s, Age = %d, Weight = %.1f\n"`

    **ADRL X0, aNameSAgeDWeigh**: 将字符串"Name = %s, Age = %d, Weight = %.1f\n"的地址加载到X0寄存器中。

    `.text:0000000000003920                 BL              .printf`

    **BL .printf**: 调用printf函数,并保存返回地址。

    `.text:0000000000003924                 FMOV            S0, #10.0`

    **FMOV S0, #10.0**: 将浮点数10.0加载到S0寄存器中。

    `.text:0000000000003928                 STR             S0, [SP,#0x20+var_14]`

    **STR S0, [SP,#0x20+var_14]**: 将S0寄存器中的值存储到堆栈指针加上var_14偏移地址指向的内存中。

    `.text:000000000000392C                 LDR             S0, [SP,#0x20+var_14]`

    **LDR S0, [SP,#0x20+var_14]**: 从堆栈指针加上var_14偏移地址处加载一个浮点数到S0寄存器。

    `.text:0000000000003930                 FCVT            D0, S0`

    **FCVT D0, S0**: 将S0寄存器中的单精度浮点数转换为D0寄存器中的双精度浮点数。

    `.text:0000000000003934                 ADRL            X0, a0f ; "%.0f\n"`

    **ADRL X0, a0f**: 将字符串"%.0f\n"的地址加载到X0寄存器中。

    `.text:000000000000393C                 BL              .printf`

    **BL .printf**: 调用printf函数,并保存返回地址。

    ### 📌 函数结尾和返回

    `.text:0000000000003940                 LDP             X29, X30, [SP,#0x20+var_s0]`

    **LDP X29, X30, [SP,#0x20+var_s0]**: 从栈中加载帧指针(X29)和链接寄存器(X30)。

    `.text:0000000000003944                 ADD             SP, SP, #0x30`

    **ADD SP, SP, #0x30**: 释放48字节的栈空间。

    `.text:0000000000003948                 RET`

    **RET**: 返回调用者,执行函数返回。


    ### 数据处理指令

    #### MOV - 数据传送

    **作用**: 将一个值传送到寄存器中。

    `MOV X0, X1        ; 将X1寄存器的值传送到X0寄存器 MOV X0, #42       ; 将立即数42加载到X0寄存器`


    #### ADD/SUB - 加法/减法

    **作用**: 对寄存器中的值进行加法或减法操作。

    `ADD X0, X1, X2    ; X0 = X1 + X2 SUB X0, X1, #10   ; X0 = X1 - 10`


    #### MUL/DIV - 乘法/除法

    **作用**: 对寄存器中的值进行乘法或除法操作。

    `MUL X0, X1, X2    ; X0 = X1 * X2 UDIV X0, X1, X2   ; X0 = X1 / X2 (无符号除法)`


    ### 逻辑指令

    #### AND/ORR/EOR - 与/或/异或

    **作用**: 对寄存器中的值进行位运算。

    `AND X0, X1, X2    ; X0 = X1 & X2 ORR X0, X1, X2    ; X0 = X1 | X2 EOR X0, X1, X2    ; X0 = X1 ^ X2`


    #### LSL/LSR - 逻辑左移/右移

    **作用**: 对寄存器中的值进行位移操作。

    `LSL X0, X1, #3    ; X0 = X1 << 3 (逻辑左移3位) LSR X0, X1, #2    ; X0 = X1 >> 2 (逻辑右移2位)`

    ### 内存访问指令

    #### LDR/STR - 加载/存储

    **作用**: 从内存加载数据到寄存器,或将寄存器中的数据存储到内存。

    `LDR X0, [X1, #8]  ; 从内存地址(X1 + 8)加载数据到X0 STR X0, [X1, #8]  ; 将X0的数据存储到内存地址(X1 + 8)`


    #### LDUR/STUR - 未对齐加载/存储

    **作用**: 从未对齐地址加载或存储数据。

    `LDUR X0, [X1, #8] ; 从未对齐地址(X1 + 8)加载数据到X0 STUR X0, [X1, #8] ; 将X0的数据存储到未对齐地址(X1 + 8)`


    ### 分支指令

    #### B - 无条件跳转

    **作用**: 无条件跳转到指定的标签。

    `B label           ; 跳转到label标签 label:     ; 目标代码`


    #### BL - 跳转并链接

    **作用**: 跳转到子函数,并保存返回地址。

    `BL func           ; 跳转到func函数,并保存返回地址 func:     ; 函数代码 RET               ; 返回调用者`


    #### BR - 寄存器跳转

    **作用**: 跳转到寄存器中存储的地址。

    `BR X0             ; 跳转到X0寄存器中存储的地址`


    #### CBNZ/CBZ - 条件跳转

    **作用**: 当寄存器不为零或为零时进行跳转。

    `CBNZ X0, label    ; 如果X0不为零,跳转到label标签 CBZ X0, label     ; 如果X0为零,跳转到label标签`


    ### 条件指令

    #### CMP - 比较

    **作用**: 比较两个寄存器的值,设置条件标志。

    `CMP X0, X1        ; 比较X0和X1`


    #### CSEL - 条件选择

    **作用**: 根据条件标志选择两个寄存器中的一个。

    `CSEL X0, X1, X2, EQ  ; 如果条件标志为EQ(相等),则X0 = X1,否则X0 = X2`

  • 相关阅读:
    ZMQ之面向服务的可靠队列(管家模式)
    Vmware安装
    【ELK 使用指南 3】Zookeeper、Kafka集群与Filebeat+Kafka+ELK架构(附部署实例)
    Moment.js 处理日期库
    游戏行业如何应对网络攻击?
    FRP原理 实战
    不懂就学—什么是autoML?
    说说Mysql的四种隔离级别
    基于springboot小型车队管理系统毕业设计源码061709
    QUIC 协议:特性、应用场景及其对物联网/车联网的影响
  • 原文地址:https://blog.csdn.net/Ben_boba/article/details/139885152