Cxxdroid 中文文档 下载 App

内联汇编 —— 在 C++ 里直接写 ARM64 指令

什么是内联汇编

内联汇编(Inline Assembly)就是在 C/C++ 代码里直接嵌入汇编指令,编译器会把这些指令原样插入到生成的机器码中。

典型用途:

Cxxdroid 官方明确宣传「支持 Clang 语法的内联汇编」——这是它和其他移动端 C/C++ 工具的差异点之一。

Clang 语法 vs GCC 语法

GCC 风格的内联汇编(最常见)长这样:

asm volatile("add %0, %1, #1" : "=r"(result) : "r"(x));

Clang 也支持这种格式(Clang 兼容 GCC 内联汇编),所以大部分 GCC 风格内联汇编代码可以直接在 Cxxdroid 里编译。

一个简单的内联汇编示例

在 Cxxdroid(ARM64 架构)里实现一个加法函数:

int add_one(int x) {
    int result;
    asm volatile(
        "add %0, %1, #1\n"
        : "=r"(result)      // 输出操作数:result 映射到任意可用寄存器
        : "r"(x)            // 输入操作数:x 映射到任意可用寄存器
        :                    // clobber list:无额外需要声明的寄存器
    );
    return result;
}

翻译成人话:

clobber list 是什么

如果内联汇编修改了某个未声明的寄存器,必须在 clobber list 里告诉编译器——否则编译器可能以为那个寄存器还存着之前的值,导致后续代码读错数据。

asm volatile(
    "mov x0, #42\n"
    :
    :
    : "x0"   // 声明修改了 x0 寄存器
);

约束字符速查

最常用的几个约束字符(适用于 ARM64):

字符含义
r任意通用寄存器
g允许寄存器、内存或立即数
m仅允许内存操作数
=r输出操作数(= 表示写)
+r读写操作数(+ 表示先读后写)

在 Cxxdroid 里验证内联汇编

  1. 新建 C++ 单文件项目
  2. 粘贴上面的 add_one 函数 + main 调用它
  3. 编译运行
  4. 如果输出正确的结果(输入 5 输出 6),说明内联汇编工作正常

注意事项

volatile vs 不 volatile

asm("nop");     // 编译器可能优化掉
asm volatile("nop");  // 编译器不能优化掉

用 volatile 告诉编译器「这段汇编有副作用,不能删掉、不能重排」。大多数内联汇编都应该加 volatile。

语法错误提示

Clang 对内联汇编的语法错误提示很清晰——会告诉你「哪个约束字符用错了」或「寄存器名无效」。如果报 invalid operand for inline asm constraint,检查一下约束字符是不是符合当前架构(ARM64 vs x86 的约束不完全一样)。

Cxxdroid 是 ARM64

重要:Cxxdroid 编译出来的可执行文件是 ARM64 架构的——所以你写的内联汇编必须是 AArch64 汇编语法,不能是 x86/x64 语法。

典型的 ARM64 vs x86 差异:

进阶:Extended Inline Assembly

如果内联汇编里有多条指令,用 asm goto 或 Extended 格式可以更清晰地组织代码。不过对于学习和实验来说,Basic Inline Assembly(上面的例子)已经够用了。