0

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.

Clement Poon
  • 79
  • 1
  • 6

1 Answers1

2

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 2
    From https://wiki.osdev.org/GAS#Intel_Syntax_Support : "It is generally discouraged to use the support for Intel Syntax because it can subtly and surprisingly different than the real Intel Syntax found in other assemblers". It's possible the `0` token may be taken as an immediate value even though that would be impossible in that position - both `ds:0` and `[0]` would change its nature. Just guessing but it does make a little sense. – paxdiablo May 09 '20 at 04:53
  • @paxdiablo: yeah, looking like an immediate was my guess at why it was rejected and why I tried `ds:0` and `[0]` to see if they'd work. And mostly agreed with that sentiment; use GNU `.intel_syntax` as a read-only format for stuff like objdump / gdb / gcc asm output unless you don't mind figuring out how to work around occasional design quirks in GAS's intel syntax. But if you really must use GNU C Extended inline asm (instead of writing a stand-alone function in NASM), it's a valid option for personal projects for sure. Glibc and Linux sources only use AT&T, though. – Peter Cordes May 09 '20 at 05:00