Skip to the content.

GCC 内联汇编教程

本教程从简单到复杂,系统性地介绍 GCC 内联汇编的使用方法,包含 12 个循序渐进的示例,支持 x86_64 和 ARM64 (AArch64) 两种架构,所有代码均可在对应架构的 Linux 环境下编译运行。

支持的架构

架构 目录 说明
x86_64 x86_64/ Intel/AMD 64位处理器
ARM64/AArch64 aarch64/ ARM 64位处理器 (包括 Apple Silicon, AWS Graviton 等)

目录结构

inline-asm-tutorial/
├── Makefile              # 自动检测架构的主 Makefile
├── README.md             # 本文件
├── x86_64/               # x86_64 架构代码
│   ├── 01_hello_asm.c
│   ├── 02_input_output.c
│   ├── 03_constraints.c
│   ├── 04_clobbers.c
│   ├── 05_memory_barrier.c
│   ├── 06_volatile.c
│   ├── 07_early_clobber.c
│   ├── 08_output_input_modifiers.c
│   ├── 09_atomic_cas.c
│   ├── 10_syscall.c
│   ├── 11_rdpmc.c
│   └── 12_cpuid.c
└── aarch64/              # ARM64 架构代码
    ├── 01_hello_asm.c
    ├── 02_input_output.c
    ├── 03_constraints.c
    ├── 04_clobbers.c
    ├── 05_memory_barrier.c
    ├── 06_volatile.c
    ├── 07_early_clobber.c
    ├── 08_output_input_modifiers.c
    ├── 09_atomic_cas.c
    ├── 10_syscall.c
    ├── 11_timer.c
    └── 12_idreg.c

快速开始

Makefile 会自动检测当前架构并编译对应的代码:

# 编译所有示例(自动检测架构)
make all

# 运行所有测试
make test

# 编译并运行单个示例
./x86_64/01_hello_asm.out
# 或
./aarch64/01_hello_asm.out

架构差异速查

寄存器命名

x86_64 ARM64 说明
rax, rbx, … x0, x1, … 64位通用寄存器
eax, ebx, … w0, w1, … 32位通用寄存器
rdi, rsi, rdx x0, x1, x2 函数/系统调用参数
rax x0 函数/系统调用返回值
r8-r15 x8-x18 额外通用寄存器

系统调用

  x86_64 ARM64
指令 syscall svc #0
系统调用号 rax x8
参数1-6 rdi, rsi, rdx, r10, r8, r9 x0-x5
返回值 rax x0
write 系统调用号 1 64
getpid 系统调用号 39 172

原子操作

  x86_64 ARM64
原子递增 lock; inc LDXR/STXR 循环
CAS lock; cmpxchg LDXR + 比较 + STXR
内存屏障 mfence dmb sy

性能计数器

  x86_64 ARM64
时间戳 rdtsc/rdtscp mrs cntvct_el0
频率 CPU 特定 mrs cntfrq_el0
序列化 cpuid isb

特性检测

  x86_64 ARM64
CPU ID cpuid 指令 读取 MIDR_EL1
特性位 cpuid 返回值 ID_AA64* 系统寄存器
缓存信息 cpuid CTR_EL0

学习路径

基础篇 (01-04)

01_hello_asm.c - 基本语法

02_input_output.c - 输入输出操作数

03_constraints.c - 约束条件

04_clobbers.c - 修改列表

进阶篇 (05-08)

05_memory_barrier.c - 内存屏障

06_volatile.c - volatile 关键字

07_early_clobber.c - 早期修改

08_output_input_modifiers.c - 修饰符详解

实战篇 (09-12)

09_atomic_cas.c - 原子操作 CAS

10_syscall.c - 系统调用

11_rdpmc.c / 11_timer.c - 性能计数器

12_cpuid.c / 12_idreg.c - 特性检测

核心概念速查

Extended Asm 语法模板

asm [volatile] (
    "汇编模板"
    : 输出操作数列表    /* 可选 */
    : 输入操作数列表    /* 可选 */
    : 修改列表          /* 可选 */
);

常用约束

约束 x86_64 ARM64 含义
r 任何通用寄存器
m 内存操作数
i 立即数
a rax/eax
b rbx/ebx
c rcx/ecx
d rdx/edx
S rsi/esi
D rdi/edi

修饰符

修饰符 含义
= 只写
+ 读写
& 早期修改

常用 Clobbers

Clobber x86_64 ARM64 含义
"memory" 修改任意内存
"cc" 修改条件码/标志位
"rax" 修改 rax
"x0" 修改 x0
"x8" 修改 x8 (syscall)

常见问题

Q: 为什么我的汇编代码被优化掉了?

A: 必须使用 __volatile__ 关键字。

Q: 输入输出使用同一寄存器导致错误?

A: 使用 & 修饰符 (early clobber) 或 + 修饰符。

Q: 多线程环境下数据不一致?

A: 添加 "memory" clobber 或使用原子指令。

Q: 如何查看生成的汇编代码?

A: 使用 make asmgcc -S

Q: 如何在 x86_64 上编译 ARM64 代码?

A: 需要交叉编译器,例如 aarch64-linux-gnu-gcc

参考资源

通用

x86_64

ARM64

许可

本教程代码供学习和参考使用。

本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。