使用CLANG内联汇编创建C ++预增量操作

Ole*_*leg 2 c++ x86 x86-64 inline-assembly clang++

我正在尝试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;
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*tch 5

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

怎么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;
}
Run Code Online (Sandbox Code Playgroud)

输出应为:

a = 1,b = 1


注意:由于除了寄存器我们没有告诉我们要修改的寄存器以外,没有其他副作用,因此不需要volatileasm语句中使用它。