ARMv8-R汇编内联语法详解
在 ARMv8-R 架构中使用 __asm__ __volatile__ 是 GCC 编译器提供的内联汇编语法,用于在 C/C++ 代码中嵌入汇编指令。以下是详细用法说明和示例:
基本语法结构
__asm__ __volatile__ (
"汇编指令" // 指令部分
: "输出操作数列表" // 输出操作数(可选)
: "输入操作数列表" // 输入操作数(可选)
: "破坏列表" // 破坏寄存器列表(可选)
);
关键组成部分解析
-
__volatile__
禁止编译器优化此段汇编,确保指令按原样执行(对硬件操作至关重要)。 -
汇编指令
- 用双引号包裹,多条指令用
\n\t分隔。 - 使用
%0,%1等占位符引用操作数。
- 用双引号包裹,多条指令用
-
操作数约束
- 输出操作数:
"=约束"(变量)(=表示只写)。 - 输入操作数:
"约束"(变量)。 - 常用约束:
r:通用寄存器。m:内存操作数。I:立即数。
- 输出操作数:
-
破坏列表(Clobber List)
声明可能被修改的寄存器或内存:"memory":表示内存被修改。"cc":表示条件标志被修改。- 寄存器名:如
"r0","r1"。
ARMv8-R 典型使用场景示例
示例 1:读取系统寄存器
uint64_t read_cntvct(void) {
uint64_t val;
__asm__ __volatile__(
"mrs %0, cntvct_el0" // 读取 CNTVCT_EL0 到 val
: "=r" (val) // 输出:val 使用通用寄存器
);
return val;
}
示例 2:写入系统寄存器
void set_daif(uint64_t value) {
__asm__ __volatile__(
"msr daif, %0" // 将 value 写入 DAIF
: // 无输出
: "r" (value) // 输入:value 存入寄存器
: "cc" // 破坏:条件标志寄存器
);
}
示例 3:内存屏障指令
void data_barrier(void) {
__asm__ __volatile__(
"dsb sy" // 数据同步屏障
::: "memory" // 破坏:内存(防止编译器乱序)
);
}
示例 4:原子操作
void atomic_increment(uint32_t *addr) {
__asm__ __volatile__(
"ldrex r1, [%0]\n" // 原子加载
"add r1, r1, #1\n" // 自增
"strex r0, r1, [%0]" // 原子存储
: // 无输出
: "r" (addr) // 输入:addr 指针
: "r0", "r1", "cc", "memory" // 破坏:寄存器 r0/r1、条件标志、内存
);
}
注意事项
-
寄存器约束
ARMv8-R 有 32 个 64 位通用寄存器(x0-x30),32 位时用w0-w30。明确指定寄存器需用asm("mov x0, #1")直接操作。 -
内存屏障
在操作硬件寄存器前,使用dsb/isb确保顺序性:__asm__ __volatile__("dsb sy\n\tisb sy" ::: "memory"); -
避免冗余破坏声明
只声明实际被修改的寄存器,过度声明会降低性能。 -
检查编译器支持
确保编译器支持 ARMv8-R(如 GCC 的-march=armv8-r选项)。
错误用法示例
// 错误:未声明破坏的寄存器
__asm__("mov r0, #1"); // 可能破坏 r0 导致程序错误
// 正确:显式声明破坏
__asm__ __volatile__(
"mov r0, #1"
: : : "r0" // 声明 r0 被修改
);
通过合理使用 __asm__ __volatile__,可直接操作 ARMv8-R 的底层硬件资源(如系统寄存器、中断控制等),适用于实时系统、固件开发等场景。
浙公网安备 33010602011771号