C/C++中 __asm volatile 函数的实现

 更新时间:2026年01月12日 09:37:51   作者:Yashar Qian  
C/C++中的__asm volatile是GCC/Clang的内联汇编语法,用于在代码中直接嵌入汇编指令,本文就来介绍一下C/C++中 __asm volatile 函数的实现,感兴趣的可以了解一下

__asm volatile 是 GCC(及兼容编译器如 Clang)中的一个特性,用于在 C/C++ 代码中内嵌汇编指令。让我们详细解释:

1. 基本概念

__asm

  • 用于嵌入汇编代码的关键字
  • 在 GCC 中,也可以用 asm(取决于编译器选项)
  • 语法:__asm__("汇编指令");__asm volatile("汇编指令");

volatile

  • 告诉编译器:不要优化这段汇编代码
  • 防止编译器因认为汇编代码"无副作用"而删除或移动它
  • 对于访问硬件寄存器、内存屏障等场景必须使用

2. 基本语法

// 简单形式
__asm volatile("nop");  // 执行空操作

// 多条指令
__asm volatile(
    "movl $1, %eax\n\t"
    "movl $2, %ebx"
);

// 带输入输出操作数
int a = 10, b;
__asm volatile(
    "movl %1, %%eax\n\t"
    "addl $5, %%eax\n\t"
    "movl %%eax, %0"
    : "=r"(b)          // 输出操作数
    : "r"(a)           // 输入操作数
    : "%eax"           // 破坏的寄存器
);

3. 扩展语法(带操作数)

// 完整语法
__asm volatile(
    "汇编指令模板"
    : 输出操作数列表     // 可选
    : 输入操作数列表     // 可选
    : 破坏的寄存器列表   // 可选
);

操作数约束

约束含义
r寄存器
m内存地址
i立即数
g寄存器/内存/立即数

4. 常见用途

内存屏障

// 防止指令重排序
__asm volatile("" ::: "memory");

// 编译器屏障
__asm volatile("" ::: "memory");

访问硬件

// 读取时间戳计数器
uint64_t rdtsc() {
    uint32_t lo, hi;
    __asm volatile(
        "rdtsc"
        : "=a"(lo), "=d"(hi)
    );
    return ((uint64_t)hi << 32) | lo;
}

系统调用

// Linux x86_64 系统调用
long syscall(long number, ...) {
    long ret;
    __asm volatile(
        "syscall"
        : "=a"(ret)
        : "a"(number)
        : "rcx", "r11", "memory"
    );
    return ret;
}

5. 重要注意事项

必须使用 volatile 的场景:

  1. 访问硬件寄存器
  2. 内存屏障操作
  3. 有副作用的汇编(修改内存或硬件状态)
  4. 系统调用

可以不使用 volatile 的场景:

  • 纯计算操作(无副作用)
  • 编译器可以安全优化的情况

6. 实际示例

// 原子加法
void atomic_add(int *ptr, int value) {
    __asm volatile(
        "lock addl %1, %0"
        : "+m"(*ptr)
        : "ir"(value)
    );
}

// 获取当前栈指针
void* get_stack_pointer() {
    void *sp;
    __asm volatile(
        "mov %%rsp, %0"
        : "=r"(sp)
    );
    return sp;
}

// 延迟一段时间(简单忙等待)
void delay_cycles(unsigned int cycles) {
    __asm volatile(
        "1:\n\t"
        "sub $1, %0\n\t"
        "jnz 1b"
        : "+r"(cycles)
    );
}

7. 跨平台考虑

不同的编译器/架构有不同的语法:

// GCC/Clang (x86)
__asm volatile("指令");

// MSVC (x86)
__asm {
    mov eax, 1
    add eax, 2
}

// ARM GCC
__asm volatile("mov r0, #1");

8. 替代方案

现代 C/C++ 中,考虑使用:

  • C11/C++11 原子操作 (<stdatomic.h>, <atomic>)
  • 编译器内置函数 (__builtin_*)
  • 特定头文件 (<xmmintrin.h> 等用于 SIMD)

总结

__asm volatile 是底层编程的强大工具,但:

  • 可移植性差(不同编译器/架构语法不同)
  • 易出错(寄存器管理、副作用处理)
  • 应作为最后手段,优先使用标准库或编译器内置功能

除非进行系统编程、内核开发或性能关键代码优化,否则通常应避免使用内联汇编。

到此这篇关于C/C++中 __asm volatile 函数的实现的文章就介绍到这了,更多相关C++ __asm volatile 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言实例讲解嵌套语句的用法

    C语言实例讲解嵌套语句的用法

    所谓嵌套(Nest),就是一条语句里面还有另一条语句,例如 for 里面还有 for,while 里 面还有 while,或者 for 里面有 while,while 里面有 if-else,这都是允许的
    2022-05-05
  • C语言实现动态版通讯录的示例代码

    C语言实现动态版通讯录的示例代码

    这篇文章主要为大家详细介绍了如何利用C语言实现一个简单的动态版通讯录,文中的示例代码讲解详细,对我们学习C语言有一定帮助,需要的可以参考一下
    2022-08-08
  • c语言可变参数实现示例

    c语言可变参数实现示例

    这篇文章主要介绍了c语言可变参数实现示例,需要的朋友可以参考下
    2014-04-04
  • C++实现十六进制字符串转换为十进制整数的方法

    C++实现十六进制字符串转换为十进制整数的方法

    这篇文章主要介绍了C++实现十六进制字符串转换为十进制整数的方法,涉及C++字符串与数制转换的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • C++ smart pointer全面深入讲解

    C++ smart pointer全面深入讲解

    一般在C/C++中,如果我们使用了pointer来指向某块heap区域,当不再需要这块区域的时候,我们需要手动删除它。如果忘了的话,就会产生memory leak
    2022-08-08
  • C++加密解密php代码的方法

    C++加密解密php代码的方法

    这篇文章主要介绍了C++加密解密php代码的方法,实例分析了基于C++实现加密解密的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • c++使用正则表达式提取关键字的方法

    c++使用正则表达式提取关键字的方法

    这篇文章给大家介绍了c++使用正则表达式提取关键字的方法,相对来说比较简单,同时给大家提到了c++通过正则表达式提取匹配到的字符串的方法,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-08-08
  • C++深入讲解初始化列表的用法

    C++深入讲解初始化列表的用法

    这篇文章主要介绍了C++成员初始化列表,除了可以使用构造函数对类成员进行初始化之外,C++还提供了另外一种初始化的方法,叫做成员初始化列表。下面来看看文章的详细吧,需要的朋友可以参考一下
    2022-04-04
  • QT中如何读写ini配置文件

    QT中如何读写ini配置文件

    ini文件在windows系统中可以存储需要持久保存的配置信息,QT界面中如何实现手动读取参数存放的位置,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • VC运用OPENGL加载BMP纹理图的实现方法汇总

    VC运用OPENGL加载BMP纹理图的实现方法汇总

    这篇文章主要介绍了VC运用OPENGL加载BMP纹理图的实现方法,对于更好的了解OpenGL很有帮助,需要的朋友可以参考下
    2014-07-07

最新评论