C++ 多线程内联汇编

C++ multithreaded inline asm

我正在寻找 运行 线程中的内联 asm,但我在某些指令上遇到段错误,例如以下指令:

#include <thread>

void Foo(int &x) 
{
    int temp;
    asm volatile ("movl , %%edx;"
                  "movl , %%eax;"
                  "addl %%edx, %%eax;"
                  "movl %%eax, -24(%%rbp);" // seg faults here
                  "movl -24(%%rbp), %0;"
                  : "=r" (temp) : : );
    x=temp;
}

int main() 
{
    int x;
    std::thread t1(Foo, std::ref(x));
    t1.join();
    return 0;
}

(我正在使用 std::ref 来传递对 std::thread 的引用,但必须使用 temp 变量,因为扩展的 asm 语法不起作用有参考文献。)

我试过破坏所有相关的寄存器,但没有用。如果我不向线程传递任何参数,它似乎可以工作:而且奇怪的是,如果我破坏 %ebx 寄存器(不涉及),它也可以工作。我在 64 位 Ubuntu 14.04.

上使用 gcc 4.8.4

我可以在线程中执行内联 asm 的 best/safest 方法是什么?

我仍然不完全相信我理解你的目标是什么。我发现评论“但必须使用临时变量,因为扩展的 asm 语法不适用于引用。”有点不寻常。我希望您可以将引用传递给汇编程序模板,因为它实际上只是一个指针。由于您使用的是人为设计的示例,因此我将保留该示例,但不包括将数据移动到堆栈上的任意位置,并且我会将被破坏的寄存器添加到列表中。你可能会选择类似的东西:

#include <thread>

void Foo(int &x) 
{
    asm volatile ("movl , %%edx;" // We clobber EDX
                  "movl , %%eax;" // We clobber EAX
                  "addl %%edx, %%eax;" // Result in EAX=3+5=8
                  "movl %%eax, %0;" // Move to variable x
                  : "=r" (x) : : "eax", "edx" );
}

int main() 
{
    int x;
    std::thread t1(Foo, std::ref(x));
    t1.join();
    return 0;
}

我已将 "eax""edx" 添加到 clobber 列表中,因为我们在汇编程序模板中销毁了它们(并且它们不显示为输入或输出约束)。您还应该注意到我没有使用临时变量。汇编代码可以简化为一条指令,因为人为设计的示例等同于 movl , %0;

您也可以像这样使用 x 的内存地址(参考):

void Foo(int &x) 
{
    asm volatile ("movl , %%edx;" // We clobber EDX
                  "movl , %%eax;" // We clobber EAX
                  "addl %%edx, %%eax;" // Result in EAX=3+5=8
                  "movl %%eax, %0;" // Move to variable x
                  : "=mr" (x) : : "eax", "edx" );
}

在这种情况下,我使用 =mr(内存操作数或寄存器)作为输出约束。这允许我们在没有中间寄存器的情况下将值右移到内存操作数。