首页 > 解决方案 > 使用 CLANG 内联汇编创建 C++ 预增量操作

问题描述

我正在尝试b = ++a;使用内联汇编执行等效操作,但是在执行代码后我的变量中出现了奇怪的值。我正在使用 clang++(g++ 兼容)来编译内联汇编。这是我到目前为止得到的:

#include <iostream>

using std::endl;
using std::cout;

int main()
{
    uint64_t a = 0;
    uint64_t b = 0;

    asm volatile(
    "pushq %%rbp;"
    "movq %%rsp, %%rbp;"
    "movl $0, -4(%%rbp);"
    "movl $0, -8(%%rbp);"
    "addq $1, -4(%%rbp);"
    "mov -4(%%rbp), %%rax;"
    "mov %%rax, -8(%%rbp);"
    "mov -4(%%rbp), %0;"
    "mov -8(%%rbp), %1;"
    "movq %%rbp, %%rsp;"
    "popq %%rbp"
    :"=r" (a), "=r" (b)
    :
    :"%rax", "%rbp", "%rsp"
    );
    cout << "a = " << a << ", b = " << b << endl;
    return 0;
}

标签: c++x86x86-64inline-assemblyclang++

解决方案


您的代码过于复杂,看来您可能已经从其他地方查看了编译器生成的代码来创建答案。

做什么b=++a;?它首先递增a,然后将该值分配给b. 在这样的表达式a中,既用作输入又用作输出。读取的值a,加 1,保存并将结果复制到b。使用 GCC 的扩展内联汇编,您可以使用约束上的修饰符a将其视为输入和输出操作数。可以使用约束上的修饰符与仅输出操作数一起使用。该指令可用于递增和复制该值的指令。+ b=INCaMOVb

内联汇编可能看起来像:

#include <iostream>

using std::endl;
using std::cout;

int main()
{
    uint64_t a = 0;
    uint64_t b = 0;

    asm ("inc %0\n\t"
         "mov %0, %1"
         : "+r" (a), "=r" (b)
    );
    cout << "a = " << a << ", b = " << b << endl;
    return 0;
}

输出应该是:

a = 1, b = 1


注意:由于除了我们告诉编译器我们要修改的寄存器之外没有其他副作用,因此没有必要volatileasm语句上使用。


推荐阅读