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
X2 与 X3 异或,结果存 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/X30,SP +=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_EL1 和 SPSR_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字节存入 X1,X1 +=16
指令记忆要点
操作数顺序:目标寄存器在前(
Xd = Xn op Xm),如ADD X0, X1, X2;立即数前缀:立即数用
#标识(如#0x10),寄存器不加前缀;位宽区分:
X开头为64位寄存器(X0-X30),W开头为32位(W0-W30);内存访问:方括号
[]表示内存地址(如[X0]为X0指向的内存数据)。
可根据具体场景(如数据运算、内存操作、函数调用)选择对应指令类别,结合寄存器使用规则(ABI规范)编写正确的汇编代码。
最后更新于