ARM64汇编寻址、汇编指令、指令编码方式

版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/

ARM64汇编寻址

1. 立即数寻址(Immediate Addressing)

这种方式直接将立即数作为操作数,适合小数据或常量。ARM64的立即数在指令中直接编码。

MOV X0, #10      ; 将常数10加载到寄存器X0中

2. 寄存器间接寻址(Register Indirect Addressing)

使用寄存器中的地址作为内存地址。适合基于寄存器值进行偏移的简单访问方式。

LDR X1, [X0]     ; 将地址X0指向的内存内容加载到X1中

3. 偏移寻址(Offset Addressing)

在基地址寄存器的基础上添加一个偏移量来确定目标地址,偏移量可以是立即数或寄存器值。

LDR X1, [X0, #8] ; 从地址X0 + 8的位置加载数据到X1中

4. 预索引寻址(Pre-indexed Addressing)

使用基地址加上偏移量来访问内存,访问完成后,将偏移量更新到基地址寄存器中。

LDR X1, [X0, #8]! ; 从地址X0 + 8加载数据到X1中,同时更新X0为X0 + 8

5. 后索引寻址(Post-indexed Addressing)

先使用基地址来访问内存,再将偏移量加到基地址寄存器中。这样偏移的效果在读取数据后才生效。

LDR X1, [X0], #8  ; 先从X0指向的地址加载数据到X1中,随后X0增加8

6. 寄存器偏移寻址(Register Offset Addressing)

偏移量用另一个寄存器指定,便于灵活的偏移操作,特别适合对数据结构的访问。

LDR X1, [X0, X2]  ; 从X0 + X2指向的内存地址加载数据到X1中

7. 带移位的寄存器偏移寻址(Scaled Register Offset Addressing)

将偏移寄存器的值进行左移,然后加到基地址中。这个方式常用于访问数组中的元素,因为它可以按数据大小自动调整偏移。

LDR X1, [X0, X2, LSL #3] ; 计算X0 + (X2 * 8)的地址,并从中加载数据到X1

LSL:逻辑左移,将寄存器的值向左移位指定的位数,右侧用 0 填充。

LSR:逻辑右移,将寄存器的值向右移位指定的位数,左侧用 0 填充。

ASR:算术右移,和逻辑右移类似,但左侧用符号位填充。即,如果值为负,左侧填充 1,如果为正,填充 0。

UXTX:执行零扩展,同时可以左移指定的位数。

SXTW/SXTX:执行符号扩展,并可以左移指定的位数。这些用于在 32 位和 64 位数据之间进行转换的场合,特别适合混合宽度数据操作。

ROR:循环右移,将寄存器的值向右旋转指定的位数,即右移的位会从左侧填入。

8. 栈寻址

使用栈指针 SP 作为基地址,加上偏移量来访问栈中的数据。例如,存储和加载局部变量

存储数据到栈

STP X29, X30, [SP, #0x70 + var_s0]  ; 将 X29 和 X30 的值存储到 SP 基址加 #0x70 + var_s0 偏移量的内存地址上

从栈加载数据

LDP X29, X30, [SP, #0x70 + var_s0]   ; 从 SP 基址加偏移 #0x70 + var_s0 处加载数据到 X29 和 X30

STP(Store Pair) 指令用于将两个寄存器的值存储到内存中(通常是栈上)。

LDP(Load Pair)指令用于从内存中同时加载两个寄存器的值。

指令中的寄存器类型决定了要读取或存储的数据大小。在上面的例子中,由于使用的是 64 位的 X 寄存器,每个寄存器占 8 字节(64 位),所以 STP 和 LDP 指令会操作两个 8 字节的数据。

MOV 和 LDR 指令的区别

MOV:用于寄存器和常量间的数据传递,不涉及内存访问。适合在不需要访问内存的情况下使用,如加载常数或在寄存器之间传递数据。

LDR:用于从内存中加载数据到寄存器,需要指定内存地址。支持多种寻址方式,例如偏移寻址、基地址寄存器加偏移等,非常适合访问内存中的数据,如全局变量、数组元素等。

两者主要区别在于是否需要访问内存。

ARM64汇编指令

ARM64 指令集具有固定长度(每条指令均为 32 位)。ARM64 包含 31 个通用寄存器(X0-X30),用于存储数据和地址;一个零寄存器(XZR),用于返回零值;以及专门的栈指针(SP)和程序计数器(PC)寄存器,用于管理函数调用和指令执行。

跳转指令:

  • B:无条件跳转到指定的地址。

  • BL:无条件跳转到指定地址并将返回地址存储在链接寄存器(LR)中,用于函数调用。

  • BR:跳转到寄存器中存储的地址。

  • CBZ/CBNZ:根据寄存器值是否为零进行跳转。

  • TBZ/TBNZ:根据寄存器中指定位的值(0或1)进行跳转。

数据处理指令:

  • MOV:将一个值或寄存器的内容传送到另一个寄存器中。

  • MVN:将寄存器值按位取反,并传送到目标寄存器。

  • AND/ORR/EOR:对寄存器数据进行按位与、或、异或运算。

  • LSL/LSR:逻辑左移或右移寄存器内容。

  • BIC:对寄存器值进行按位与取反运算,用于清除特定位。

算术指令:

  • ADD/ADDS:对两个寄存器内容相加,ADDS会更新条件标志。

  • SUB/SUBS:对两个寄存器内容相减,SUBS会更新条件标志。

  • MUL:对两个寄存器内容相乘。

  • UDIV/SDIV:无符号/有符号除法,将结果存储在目标寄存器中。

  • NEG:对寄存器中的值取反并加1,相当于求负。

内存访问指令:

  • LDR:从内存加载一个值到寄存器。

  • STR:将寄存器的值存储到内存中。

  • LDUR/STUR:使用偏移量从内存加载或存储数据,不会影响基址寄存器。

  • LDXR/STXR:用于原子操作的加载和存储指令,用于处理并发数据。

  • LDP/STP:从内存加载或存储两个连续的寄存器内容,常用于函数调用保存/恢复寄存器。

如何查看ARM官方文档

打开 ARM 官方网站 ,路径 Home / Documentation / Architectures / CPU Architecture 找到 ARM64 指令集文档

可以在线查看,也可以点击左边的下载按钮下载 pdf 到本地

ARM64指令编码方式

以 MOV(bitmask immediate) 指令为例,文档中搜索 MOV 可以找到该指令的编码格式说明。

MOV(bitmask immediate) 指令的 32 位二进制格式,其中各字段的含义如下:

  • sf(位 31):size flag,指定操作数的位宽。sf=0 表示 32 位操作,sf=1 表示 64 位操作。

  • opc(位 29-23):操作码字段,用于区分不同的操作类型。对于 MOV 指令,其操作码固定为 0110010。

  • N(位 22):与立即数编码相关,用于调整立即数的生成规则。

  • immr 和 imms(位 21-10):立即数字段,用于构造一个特定的位掩码。

  • Rn(位 9-5):源寄存器字段。在 MOV(bitmask immediate)中,该字段固定为 11111,表示使用零寄存器(WZR 或 XZR),以便执行立即数到寄存器的移动操作。

  • Rd(位 4-0):目标寄存器字段,指定立即数写入的目标寄存器编号。

以下面汇编指令为例

mov w0, #1

32 位指令编码中的各字段定义如下

字段 说明
31 sf 设为 0,表示 32 位操作
30-29 固定位 固定为 01
28-23 opc 操作码,固定为 100100
22 N 设为 0
21-16 immr 000000,意味着掩码宽度为 1,即只生成一个 1,其他位全部为 0。
15-10 imms 000000,表示不进行任何旋转。
9-5 Rn 固定为 11111,表示使用零寄存器(XZR)
4-0 Rd 目标寄存器 X0 的编码为 00000

将以上字段组合,我们得到完整 32 位二进制编码如下

0 01 100100 0 000000 000000 11111 00000

十六进制值为 320003E0,转换为小端模式值为 E0030032

https://armconverter.com/?disasm 验证一下是否正确

相关文章:详解ARM64可执行程序的生成过程

相关推荐
长亭外的少年22 分钟前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
建群新人小猿3 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神4 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
兰琛4 小时前
20241121 android中树结构列表(使用recyclerView实现)
android·gitee
Y多了个想法5 小时前
RK3568 android11 适配敦泰触摸屏 FocalTech-ft5526
android·rk3568·触摸屏·tp·敦泰·focaltech·ft5526
NotesChapter6 小时前
Android吸顶效果,并有着ViewPager左右切换
android
_祝你今天愉快7 小时前
分析android :The binary version of its metadata is 1.8.0, expected version is 1.5.
android
暮志未晚Webgl7 小时前
109. UE5 GAS RPG 实现检查点的存档功能
android·java·ue5
麦田里的守望者江8 小时前
KMP 中的 expect 和 actual 声明
android·ios·kotlin
Dnelic-8 小时前
解决 Android 单元测试 No tests found for given includes:
android·junit·单元测试·问题记录·自学笔记