linuxassemblygccinline-assembly

ambiguous operand size for `mov' while benchmarking x86 operations


I'm writing up a benchmark to compare the movbe operation against mov; bswap to find out which is faster.

I used to write "extern C function ..." up until now, but for specific reasons i can't install NASM or any additional software besides gcc on the target system, so I'm stuck with inline assembly.

I wrote this code:

#include <time.h>
#include <stdio.h>

void movBeBenchmark(void);
void movBswapBenchmark(void);

/*
    benchmarks the movbe instruction with ecx as counter
    uses easy to read values, for ez debugging
    (check whether values are reversed)
*/
void movBeBenchmark(){

    //bring the stack into a well defined format, initialize counter
    __asm volatile( ".intel_syntax noprefix\n"
                    "mov [ebp-4],  11112222\n"
                    "mov [ebp-8],  33334444\n"
                    "mov [ebp-12], 55556666\n"
                    "mov [ebp-16], 77778888\n"
                    "mov [ebp-20], 9999aaaa\n"
                    "mov [ebp-24], bbbbcccc\n"
                    "mov [ebp-28], ddddffff\n"
                    "mov [ebp-32], 12345678\n"
                    "mov ecx, 10000\n"
                    );  //10K loops should suffice for benchmarking

    //start a timer for benchmarking
    float startTime = (float)clock()/CLOCKS_PER_SEC;

    //TODO: debug this and check values!!!
    __asm volatile( ".intel_syntax noprefix\n"
                    "LOOP: \n"
                    "movbe r8, [ebp-4]\n"
                    "movbe r9, [ebp-8]\n"
                    "movbe r10, [ebp-12]\n"
                    "movbe r11, [ebp-16]\n"
                    "movbe r12, [ebp-20]\n"
                    "movbe r13, [ebp-24]\n"
                    "movbe r14, [ebp-28]\n"
                    "movbe r15, [ebp-32]\n"
                    "movbe [ebp-4], r8\n"
                    "movbe [ebp-8], r9\n"
                    "movbe [ebp-12], r10\n"
                    "movbe [ebp-16], r11\n"
                    "movbe [ebp-20], r12\n"
                    "movbe [ebp-24], r13\n"
                    "movbe [ebp-28], r14\n"
                    "movbe [ebp-32], r15\n"
                    "loop @LOOP\n"
                    );

    //stop timer
    float endTime = (float)clock()/CLOCKS_PER_SEC;

    fprintf(stdout, "Function took %.6f units to execution!\n", startTime - endTime);
}


int main(){

    fprintf(stdout, "MovBe Benchmark\n");
    movBeBenchmark();

    return 0;
}

However, I am getting a lot of errors and can't make out why these operations are failing. My output is

gcc main.c -o benchmark
main.c: Assembler messages:
main.c:16: Error: ambiguous operand size for `mov'
main.c:17: Error: ambiguous operand size for `mov'
main.c:18: Error: ambiguous operand size for `mov'
main.c:19: Error: ambiguous operand size for `mov'
main.c:20: Error: junk `aaaa' after expression
main.c:21: Error: operand size mismatch for `mov'
main.c:22: Error: operand size mismatch for `mov'
main.c:23: Error: ambiguous operand size for `mov'
/tmp/cctHuXIm.s:35: Error: operand type mismatch for `cvtsi2ss'
/tmp/cctHuXIm.s:36: Error: junk `(%rip)' after expression
/tmp/cctHuXIm.s:38: Error: junk `(%rbp)' after expression
main.c:49: Error: bad expression
main.c:49: Error: junk `LOOP' after expression
/tmp/cctHuXIm.s:64: Error: operand type mismatch for `cvtsi2ss'
/tmp/cctHuXIm.s:65: Error: junk `(%rip)' after expression
/tmp/cctHuXIm.s:67: Error: junk `(%rbp)' after expression
/tmp/cctHuXIm.s:68: Error: junk `(%rbp)' after expression
/tmp/cctHuXIm.s:69: Error: junk `(%rbp)' after expression
/tmp/cctHuXIm.s:71: Error: junk `(%rip)' after expression
/tmp/cctHuXIm.s:72: Error: no such instruction: `movl $.LC1,%esi'
/tmp/cctHuXIm.s:73: Warning: mnemonic suffix used with `mov'
/tmp/cctHuXIm.s:73: Warning: NOTE: Such forms are deprecated and will be rejected by a future version of the assembler
/tmp/cctHuXIm.s:74: Error: no such instruction: `movl $1,%eax'
/tmp/cctHuXIm.s:92: Warning: mnemonic suffix used with `push'
/tmp/cctHuXIm.s:95: Warning: mnemonic suffix used with `mov'
/tmp/cctHuXIm.s:97: Error: junk `(%rip)' after expression
/tmp/cctHuXIm.s:98: Warning: mnemonic suffix used with `mov'
/tmp/cctHuXIm.s:99: Error: no such instruction: `movl $16,%edx'
/tmp/cctHuXIm.s:100: Error: no such instruction: `movl $1,%esi'
/tmp/cctHuXIm.s:101: Error: no such instruction: `movl $.LC2,%edi'
/tmp/cctHuXIm.s:104: Error: no such instruction: `movl $0,%eax'
/tmp/cctHuXIm.s:105: Warning: mnemonic suffix used with `pop'

Of course I already fiddled around with the operations, tried using DWORD PTRs and googled for the errors. This is where my luck ran out.

I seem to have problems with the mov instruction and also with the LOOP label. However, this should be valid x86 code, shouldn't it? Why can't my gcc just inline these operations?

Pls help and elaborate


Solution

  • It's a really bad idea to switch syntaxes in inline assembly. Remove the syntax directive and instead compile with -masm=intel. The errors you get are because gcc uses AT&T syntax for its own code, but you just switched to Intel syntax, confusing the assembler.

    There's more wrong with your code:

    It may be best for your application to just place the assembly code into an assembly file and include that file into the build. Gcc uses the GNU assembler and can pass assembly files to the assembler if asked to compile them. No extra software needs to be installed.