ARMv8 指令

编程模型

ARMv8 架构下的编程模型

AArch64 架构的寄存器组划分为通用寄存器、特殊寄存器和向量寄存器,具体如下:

寄存器类型

数量

关键寄存器

用途

通用寄存器(64位)

31个

X0-X7

函数参数/返回值(前8个参数)

X19-X28

非临时寄存器(被调用者保存)

X29 (FP)

帧指针(栈帧基地址)

X30 (LR)

链接寄存器(函数返回地址)

SP

栈指针(16字节对齐)

特殊寄存器

-

PSTATE

程序状态寄存器(N/Z/C/V标志位、异常级别)

PC

程序计数器(下一条指令地址)

NEON向量寄存器

32个

V0-V31 (128位)

SIMD/浮点运算(多媒体、科学计算加速)

示例:函数调用时的寄存器使用

// 调用 func(a, b, c),参数通过 X0-X2 传递
mov x0, #1          // a = 1
mov x1, #2          // b = 2
mov x2, #3          // c = 3
bl func             // 结果存于 X0

指令集

操作码和操作数:

  • 操作码:直接对应硬件电路的控制型号

  • 操作数:操作码作用的对象,操作谁,结果放哪。

ARM 操作码固定为 32 bit,后面的操作数的类型和数量根据操作码确定。

一些常见的指令

一、数据处理指令(算术/逻辑运算)

指令

功能描述

示例

说明

ADD Xd, Xn, Xm

寄存器加法

ADD X0, X1, X2

X0 = X1 + X2(64位运算)

ADD Xd, Xn, #imm12

立即数加法

ADD X3, X4, #0x20

X3 = X4 + 32(12位立即数,0~4095)

SUB Xd, Xn, Xm

寄存器减法

SUB W5, W6, W7

W5 = W6 - W7(32位运算,W=32位寄存器)

AND Xd, Xn, Xm

按位与(掩码操作)

AND X0, X0, #0xFF

X0 保留低8位,其余位清0

ORR Xd, Xn, #imm12

按位或(置位操作)

ORR X1, X1, #(1<<5)

X1 的第5位置1(立即数支持移位编码)

EOR Xd, Xn, Xm

按位异或(翻转位)

EOR X2, X2, X3

X2X3 异或,结果存 X2

LSL Xd, Xn, #shift

逻辑左移

LSL X4, X4, #2

X4 = X4 << 2(左移2位,低位补0)

CMP Xn, Xm

比较(更新标志位,不存结果)

CMP X0, #10; B.GT loop

X0 > 10,跳转到 loop 标签

二、加载/存储指令(内存数据传输)

指令

功能描述

示例

说明

LDR Xd, [Xn, #imm9]

基址+偏移加载(正数偏移)

LDR X0, [X1, #8]

X0 = 内存[X1 + 8](8字节对齐访问)

LDUR Xd, [Xn, #-imm9]

基址+负偏移加载

LDUR X2, [SP, #-16]

X2 = 内存[SP - 16](栈空间读取)

STR Xd, [Xn, #imm9]

基址+偏移存储

STR X3, [X4, #0x10]

内存[X4 + 16] = X3

STP Xn, Xm, [SP, #-imm]!

栈上存储两个寄存器(压栈)

STP X29, X30, [SP, #-16]!

压入 X29(FP)和 X30(LR),SP -=16

LDP Xn, Xm, [SP], #imm

栈上加载两个寄存器(弹栈)

LDP X29, X30, [SP], #16

弹出 X29/X30SP +=16

MOV Xd, #imm16

加载小立即数(16位内)

MOV X0, #0x1234

X0 = 0x1234(立即数超出16位需用 MOVZ

ADRP Xd, label

加载标签页地址(大地址拆分)

ADRP X0, data; ADD X0, X0, :lo12:data

两步加载 data 全局变量地址(64位地址)

三、控制流指令(程序跳转与函数调用)

指令

功能描述

示例

说明

B label

无条件跳转

B main

跳转到 main 标签处执行

B.cond label

条件跳转(依赖标志位)

CMP X0, #0; B.EQ exit

X0 == 0,跳转到 exit(EQ=等于)

BL func

带返回地址的跳转(函数调用)

BL printf

调用 printf,返回地址存入 X30(LR)

RET

函数返回

RET

等价于 BR X30(跳转到 LR 保存的地址)

BR Xn

寄存器间接跳转

BR X1

跳转到 X1 存储的地址(动态跳转)

CBZ Xn, label

比较并为零跳转(简化 CMP + B.EQ

CBZ X0, error

X0 == 0,跳转到 error

CBNZ Xn, label

比较并非零跳转

CBNZ X2, loop

X2 != 0,跳转到 loop

四、栈操作与寄存器管理(遵循ARM64 ABI)

场景

示例代码

说明

函数栈帧创建

asm sub sp, sp, #32 // 分配32字节栈空间 stp x29, x30, [sp, #16] // 保存FP和LR mov x29, sp // 更新FP指向栈顶

符合ARM64 ABI规范,栈帧需16字节对齐

函数参数传递

asm mov x0, #1 // 第1个参数:1 mov x1, #2 // 第2个参数:2 bl add_func // 调用 add_func(1,2)

前8个参数通过 X0-X7 传递,结果存 X0

临时寄存器保护

asm str x19, [sp, #8] // 保存非临时寄存器X19(被调用者负责) ... ldr x19, [sp, #8] // 恢复X19

X19-X28 为非临时寄存器,需压栈保护

五、系统指令与异常处理

指令

功能描述

示例

说明

SVC #imm

触发系统调用(用户态→内核态)

SVC #0

陷入内核态,调用系统调用号0(如 exit

MSR SPSel, #1

切换栈指针(EL0→EL1)

MSR SPSel, #1

从用户栈(SP_EL0)切换到内核栈(SP_EL1)

MRS Xd, NZCV

读取状态寄存器标志位

MRS X0, NZCV

X0 获取 PSTATE 中的 N/Z/C/V 标志位

ERET

异常返回

ERET

从异常处理返回,恢复 ELR_EL1SPSR_EL1

六、NEON向量指令(SIMD加速)

指令

功能描述

示例

说明

ADD Vd.4S, Vn.4S, Vm.4S

4个32位整数并行加法

ADD V0.4S, V1.4S, V2.4S

V0[0-3] = V1[0-3] + V2[0-3](SIMD加速)

LD1 {Vd.8B}, [Xn]

加载8个字节到向量寄存器

LD1 {V3.8B}, [X0]

X0 地址加载8字节,存入 V3 的8个字节通道

ST1 {Vd.16B}, [Xn]!

存储16字节到内存(后更新地址)

ST1 {V4.16B}, [X1]!

V4 的16字节存入 X1X1 +=16

指令记忆要点

  1. 操作数顺序:目标寄存器在前(Xd = Xn op Xm),如 ADD X0, X1, X2

  2. 立即数前缀:立即数用 # 标识(如 #0x10),寄存器不加前缀;

  3. 位宽区分X 开头为64位寄存器(X0-X30),W 开头为32位(W0-W30);

  4. 内存访问:方括号 [] 表示内存地址(如 [X0]X0 指向的内存数据)。

可根据具体场景(如数据运算、内存操作、函数调用)选择对应指令类别,结合寄存器使用规则(ABI规范)编写正确的汇编代码。

最后更新于