1
votes

When I try to compile the following, gcc fails with

error: inconsistent operand constraints in an 'asm'"

Unfortunately, when I pull the function into a standalone file it compiles fine, so I'm really not sure what the issue is. The idea behind the function is to provide a wrapper around a function written in assembly that will enforce the expected calling convention regardless of the target platform.

int wrap(int(*asmfn)(int,int,int,int), int param1, int param2, int param3, int param4) {
    int x;
    asm ( "push %1;"            //save the input operand so it's not clobbered
          "push %5;"            //push the params RTL
          "push %4;"
          "push %3;"
          "push %2;"
          "call *%1;"           //call the function
          "pop %2;"             //caller cleanup / restore the param operands so they are not clobbered
          "pop %3;"
          "pop %4;"
          "pop %5;"
          "pop %1;"             //restore the other operand so it's not clobbered
          "mov %%eax, %0;"      //save the retval to a local
          : "=X" (x)
          : "c" (asmfn), "d" (param1), "b" (param2), "S" (param3), "D" (param4)
          : "cc", "memory", "%eax" );
    return x;
}

I've tried constraining the output operand into either memory only or a register, or even constraining it specifically into eax and dropping "%eax" from the clobber list, but I get the same error either way. What am I missing?

1
@KarolyHorvath There was a reason for it at one point, but regardless I still get the error. I updated the question to make it a little less unusual looking.user3314204
I think it's objecting because you are using ALL available registers, and then saying you are clobbering %eax. The only register mentioned in your list is %esp and %ebp, so %0 will probably be stored in %eax - hence, you can't also clobber %eax.Mats Petersson
@MatsPetersson I thought that might be an issue, which is why I tried the workarounds in the last paragraph of the question but it still gave the same error. I've also tried completely removing everything from the clobber list just as an experiment (although this would obviously lead to wrong code) and still get the error.user3314204
Aha, found the issue but can't post it as an answer for 8 hours... hopefully I'll remember to come back and post it so other people who have this issue can find the answer.user3314204
Clang produces a bunch of "instruction requires: Not 64-bit mode" error messages, and in 32-bit mode it does appear to work. Perhaps you need different qualifiers on the push/pop instructions?bames53

1 Answers

1
votes

After much experimentation I realized the issue and why it wasn't causing an error when standalone: this was in code being compiled into a shared object, and hence "-fPIC" was enabled. This causes gcc to use ebx to store current eip on entrance to a function so it can find the GOT via a relative offset from the function (which is known at compile time) so that the code can be position independent. As a result, any inline assembly in PIC that uses ebx as an operand will give this completely opaque error.