3
votes

GCC inline assembly error: Error: junk `(%esp)' after expression

I'm studying gcc inline assembly. My environment is Win 7 32bit, mingw-gcc 4.6.1.

I have got a problem about the 'm' constraint. Here is my c function code:

static int asm_test(int a, int b)
{

    int c = 0;
    __asm__ __volatile__(".intel_syntax\n"
            "mov eax, %1\n" //error
            "mov edx, %2\n" //error
            "add eax, edx\n"
            "mov %0, eax\n" //error
            ".att_syntax"
            :"=m"(c)\
            :"m"(a),"m"(b)\
            :"eax","edx"
            );
    return c;
}

For at&t code, it is like this:

static int asm_test(int a, int b)
{

    int c = 0;
    __asm__ __volatile__(
            "movl %1, $eax\n" //error
            "movl %2, $edx\n" //error
            "addl $edx, $eax\n"
            "movl $eax, %0\n" //error
            :"=m"(c)\
            :"m"(a),"m"(b)\
            :"eax","edx"
            );
    return c;
}

For each of the three lines which operate input/output operands, gcc generate an error when compiling, read like this:

C:\Users\farta\AppData\Local\Temp\cc99HxYj.s:22: Error: junk `(%esp)' after expression

If i use 'r' for input/output constraint, the code will work. But I cannot understand why it works and what the error stands for. Can anyone tell me? As far as I know 'm' is just telling gcc not to allocate registers but directly access them in memory if inline asm code try to access input/output operands. Is this correct?

Thanks a lot.

1
I'm not sure you can use Intel syntax in there. Try with AT&T.Mat
Thanks. I have tried equivalent at&t asm code. The error message are all the same. I think it is not caused by Intel syntax.farta
Well show the AT&T syntax. Most people who do GCC inline assemble will be more familiar with that than Intel.Mat
AT&T syntax is: asm __volatile__( "movl %1, $eax" "movl %2, $edx" "addl $edx, $eax" "movl $eax, %0" :"=m"(c)\ :"m"(a),"m"(b)\ :"eax","edx" )farta
Please edit your question to add the code, it's very hard to read in comments. In general, you should always edit your question when clarifications are requested in comments, so that everyone sees the extra information directly. (There's an "edit" link right under the tags you can use.)Mat

1 Answers

4
votes

The problem here is the GCC generates AT&T syntax construct for %0, %1 and %2. If you look at the generated assembly, it looks like:

.intel_syntax
mov eax, 8(%ebp)
mov edx, 12(%ebp)
add eax, edx
mov -4(%ebp), eax

which is not a valid Intel syntax.

Generally, you don't need to include in the inline assembly explicit load/store operation - just specify register constraint and the compiler will generate loads/stores by itself. This has the advantage that even if your variables (parameters, locals) do not reside in memory at all, but are in registers your code will still be correct - unlike in the case if you explicitly put memory load/stores there.

For your example, try the following code, look at the assembly (gcc -S) and notice how the compiler will perform moves from argument area (e.g. stack on x86) all by itself.

int asm_test(int a, int b)
{
  __asm__ __volatile__ (
                        ".intel_syntax\n"
                        "add %0, %1 \n"
                        ".att_syntax \n"
                        :"+r"(a)
                        :"r"(b));
  return a;

}