Skip to content

A64指令集

ARMv8 增加了新的 64 位指令集—— A64,它可以处理 64 位宽的寄存器和数据并且使用 64 位的指针来访问内存,但是其指令集的指令宽度依然是 32 位。ARMv8 兼容 A32 指令集,但 A64 指令集和 A32 指令集是不兼容的。

ARMv8 支持两种执行状态—— AArch64 和 AArch32。AArch64 状态用于执行 64 位指令,而 AArch32 状态用于执行 32 位指令。

加载与存储指令

LDR和STR指令

ldr 目标寄存器, <存储器地址>    //把存储器地址的数据加载到目标寄存器

str 源寄存器, <存储器地址>      //把源寄存器中的数据存储到存储器地址
ldr     x1,=0xE0000000  ;x1=0xE0000000
ldr     x1,0xE0000000   ;将内存中地址为0xE0000000的内容载入到x1
ldr     x1,[x0]         ;将x0中的数所指定的地址的内容传输到x1

入栈与出栈

函数传递的参数如果少于8个,则使用 X0-X7 寄存器传递,如果多于8个,则使用栈传递。SP 指针指向栈顶,从栈底到栈顶的这段空间,称为栈帧。

A32 指令集提供了PUSHPOP指令来实现入栈与出栈,但是 A64 指令集已经移除,而转而使用加载与存储指令。

MOV指令

MOV指令只能用于数据在寄存器之间的搬移,以及往寄存器里写立即数。

算术与移位指令

条件操作码

PSTATE 中有四个条件标志位,分别是N、Z、C、V,代表上一次运算的结果。

条件标志位 含义
N 负数
Z
C 进位
V 溢出

ADD与SUB指令

有三种用法:

  • 使用立即数
  • 使用寄存器
  • 使用移位操作

ADDSSUBS:表示指令结果会影响 PSTATE 寄存器的标志位

ADCSBC:带进位,计算时需要考虑 PSTATE 寄存器的C标志位

移位指令

  • LSL:逻辑左移
  • LSR:逻辑右移
  • ASR:算术右移
  • ROR:循环右移

逻辑移位和算术移位的区别在于是否考虑符号位。

位操作指令

  • AND:按位与
  • ORR:按位或
  • EOR:按位异或
  • BIC:位清除

比较与跳转指令

CMP指令

比较两个数的大小,有三种用法:

  • 使用立即数
  • 使用寄存器
  • 使用移位操作

跳转与返回指令

跳转指令:

  • B:无条件跳转
  • B.cond:条件跳转
  • BL:带返回地址的跳转
  • BR:跳转到寄存器指定的地址
  • BLR:带返回地址的BR

返回指令:

  • RET:通常用于子函数的返回,返回地址保存在 LR
  • ERET:从当前的异常模式返回,它会把 SPSR 的内容恢复到 PSTATE 寄存器中。该指令可以实现处理器模式的切换。

比较并跳转指令:

  • CBZ:如果寄存器为0,则跳转
  • CBNZ:如果寄存器不为0,则跳转

其他重要指令

PC相对地址加载指令

ADR指令用于加载一个在当前 PC 值 ±1MB 范围内的 label 地址到 Xd 寄存器中。

LDR和ADR指令的区别

LDR 伪指令加载的是绝对地址,即程序编译时的链接地址。ADR 加载的是当前 PC 的相对地址,可以理解为当前运行时 label 的物理地址。由于运行地址和链接地址可能不同,因此需要在不同场景下选择使用。

内存独占指令

ARMv8 体系提供独占的内存访问(exclusive memory access)指令。LDXR指令尝试在内存总线中申请一个独占访问的锁,然后访问一个内存地址。STXR指令会往刚才LDXR指令已经申请独占访问的内存地址中写入新内容。这两个指令配合使用来完成一些同步操作。

异常处理指令

  • SVC:系统调用指令,陷入 EL1
  • HVC:虚拟化系统调用指令,陷入 EL2
  • SMC:安全监控系统调用指令,陷入 EL3

系统寄存器访问指令

在 ARMv7 体系结构中,通过 CP15 协处理器可以访问系统寄存器。在 ARMv8 体系结构中,访问的方式有了大幅的改进和优化。MRSMSR两条指令可以直接访问系统寄存器。

  • MRS:读取系统寄存器的值到通用寄存器
  • MSR:将通用寄存器的值写入系统寄存器

访问SCTLR

mrs x20, sctlr_el1
msr sctlr_el1, x20

除了访问系统寄存器之外,MRSMSR指令还可以访问与 PSTATE 寄存器相关的字段,比如 CurrentEL 等。

内存屏障指令

  • DMB:数据存储屏障
  • DSB:数据同步屏障
  • ISB:指令同步屏障

除此之外,ARMv8 还提供了一组新的加载和存储指令,显示包含了内存屏障功能:

  • LDAR:加载-获取指令,LDAR指令后面的读写内存指令必须在LDAR指令之后才能执行
  • STLR:存储-释放指令,所有的加载和存储指令必须在STLR指令之前完成