简体   繁体   中英

C++ multithreaded inline asm

I'm looking to run inline asm in a thread but I get a seg fault on certain instructions, such as the below:

#include <thread>

void Foo(int &x) 
{
    int temp;
    asm volatile ("movl $5, %%edx;"
                  "movl $3, %%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;
}

(I'm using std::ref to be able to pass a reference to an std::thread , but have to use the temp variable because the extended asm syntax doesn't work with references.)

I've tried clobbering all involved registers and it doesn't help. If I don't pass any arguments to the thread, it seems to work: and it strangely also works if I clobber the %ebx register (which isn't involved). I'm using gcc 4.8.4 on 64-bit Ubuntu 14.04.

What is the best/safest way I can execute inline asm in a thread?

I'm still not completely convinced I understand what your objectives are. I find the comment " but have to use the temp variable because the extended asm syntax doesn't work with references. " a bit unusual . I'd expect you can pass a reference into an assembler template since it really is just a pointer under the hood. Since you are using a contrived example, I'll maintain that, but exclude the move of data to an arbitrary location on the stack, and I'll add the registers that get clobbered to the list. You could probably go with something like:

#include <thread>

void Foo(int &x) 
{
    asm volatile ("movl $5, %%edx;" // We clobber EDX
                  "movl $3, %%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;
}

I've added "eax" and "edx" to the clobber list since we destroy them in our assembler template (and they don't appear as input or output constraints). You should also notice I don't use a temporary variable. The assembler code can be reduced to a single instruction since the contrived example is the equivalent of movl $8, %0; .

You could also use the memory address (reference) to x like this:

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

In this case I use =mr (memory operand or register) as an output constraint. This allows us to move a value right to the memory operand without an intermediate register.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM