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可执行程序的生成过程

相关推荐
liuluyang5301 小时前
ARM DStream仿真器脚本常用命令
arm开发·dstream
每次的天空2 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭2 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日3 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安3 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑3 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟7 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡9 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi009 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil10 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android