Search code examples
gccx86inline-assemblygnu-assemblerintel-syntax

invalid instruction suffix for mov?


I have this piece of inline assembly code that should print A in text mode:

    void print(){
        asm volatile(
            "mov ax,0xb800\n"
            "mov ds,ax\n" /*<-as complains about this*/
            "movb 0,'A'\n"
    ); 
} 

However when I try to compile it with gcc(with -m32 and -masm=intel):

./source/kernel.c: Assembler messages:
./source/kernel.c:4: Error: invalid instruction suffix for `mov'

btw this piece of code is from my operating system's kernel, so I can't use stdio.h or something like that.


Solution

  • Despite GCC's line numbering in the error message, that's not the line it's actually complaining about, it's the movb store. You can test that by commenting the other instructions. The error is actually printed by the assembler, with numbering based on .loc metadata directives from the compiler, and this is a multi-line asm template, so it's easy for that to go wrong I guess.

    I suspect GAS .intel_syntax mode treats a literal 0 as an immediate, for consistency with mov al, 0 with 0 as a source operand. This of course can't work as a destination.

    The "invalid instruction suffix" error message makes little sense, although note that Intel syntax doesn't use operand-size suffixes. (For some reason movb [0], 'A' is accepted, though.)

    Instead use square brackets to avoid ambiguity; recommended for any memory operand, even if the address is a symbol instead of a literal number.

        mov  byte ptr [0], 'A'
    

    mov byte ptr ds:0, 'A' also works, and is the syntax objdump -d -Mintel uses.

    It's a good idea to always use square brackets on memory operands to remove any ambiguity, especially for people who might be used to the NASM flavour of Intel syntax.