Community
cancel
Showing results for 
Search instead for 
Did you mean: 
I-Ting_L_
Beginner
171 Views

inline assembly causes ICC to generate invalid instruction

Hi,

I am trying to compile a piece of code that uses GCC style inline assembly using Intel C++ compiler (ICC 13.0.0).

It seems that the following inline assembly causes ICC to output invalid assembly:

asm volatile (
"movq %0, %%rax\n\t"
"movq %%rbp, 16(%%rax)\n\t"
"movq %%rsp, 8(%%rax)\n\t"
"leaq 4(%%rip), %%rbx\n\t"
"movq %%rbx, 24(%%rax)\n\t"
: : "g" (frame) : "rax", "rbx" );

which produces the assembly code as expected, but after the sequence, a "lea 0" is generated.

Strangely, if I were to split this sequence into two pieces:

asm volatile (
"movq %0, %%rax\n\t"
"movq %%rbp, 16(%%rax)\n\t"
"movq %%rsp, 8(%%rax)\n\t"
: : "g" (frame) : "rax", "rbx" );
asm volatile (
"leaq 4(%%rip), %%rbx\n\t"
"movq %%rbx, 24(%%rax)\n\t"
: : : "rbx" );

then it compiles just fine, outputting expected code.  

When I used gcc to compile either piece, things compile just fine.
I am wondering if I am doing something invalid in my inline assembly, or is the code triggering a bug in the compiler.
I have attached a small piece of C code that triggers this behavior.  Any help is greatly appreciated.

Thanks,
Angelina 

0 Kudos
4 Replies
TimP
Black Belt
171 Views

If you can support the importance of this usage, and verify a problem in a current compiler release, a problem report would be indicated, when the problem report system comes back on line.

I-Ting_L_
Beginner
171 Views

The sequence of assembly essentially captures the stack pointer, base pointer, and program counter value of a function instance, and store those values into a struct.

asm volatile (
"movq %0, %%rax\n\t"
"movq %%rbp, 16(%%rax)\n\t"
"movq %%rsp, 8(%%rax)\n\t"
"leaq 4(%%rip), %%rbx\n\t"
"movq %%rbx, 24(%%rax)\n\t"
: : "g" (frame) : "rax", "rbx" );

The program counter is used by another thread to resume the function instance, at the program point right after the assembly sequence.  (Hence it's storing %rip + 4).  A possible work-around is to write the assembly sequence as the following:

asm volatile (
"movq %0, %%rax\n\t"
"movq %%rbp, 16(%%rax)\n\t"
"movq %%rsp, 8(%%rax)\n\t"
: : "g" (frame) : "rax", "rbx" );

asm volatile ("leaq 4(%%rip), %%rbx\n\t"
"movq %%rbx, %0\n\t" : "=g"(frame->rip) : : "rax", "rbx");

but the problem is, it's no longer clear that %rip+4 is the right value to store in the frame, because I don't know for sure how many instructions this sequence ends up generating.  I can look at the assembly output (right now it's just one instruction), but it's rather fragile.  If the compiler version changes or different set of compiler flags are used, there is no guarantee that the as the last instruction "movq %%rbx, %0" will be generated the same way.

Is there another work-around that you can suggest?

Thanks,
Angelina

jimdempseyatthecove
Black Belt
171 Views

Untested code:

[cpp]
asm volatile (
            "movq %0, %%rax\n\t"
            "movq %%rbp, 16(%%rax)\n\t"
            "movq %%rsp, 8(%%rax)\n\t"
            "movq %%rip, %%rbx\n\t"
            "leaq 8(%%rbx), %%rbx\n\t"
            "movq %%rbx, 24(%%rax)\n\t"
            : : "g" (frame) : "rax", "rbx" );
[/cpp]

Jim Dempsey

I-Ting_L_
Beginner
171 Views

Thanks!  That seems to work (compiles correct at least).
I don't know why I had the impression that one can't simply do a movq on %rip, but apparently I was mistaken.

Thanks,
Angelina 

Reply