You can also supply -masm=intel to gcc to use Intel syntax in assembly output (-S) and in extended inline assembly (asm volatile ("instructions" : outputs : inputs : clobbers);).
Similarly, with GNU as (part of binutils), you can use .intel_syntax noprefix at the beginning of the source file, to use Intel syntax.
I don't remember exactly which versions of as and gcc started supporting these, though. They aren't new, but they were not initially supported either.
To get the same machine code from as as my previous listing produces using nasm, you do need slight changes:
.arch i386
.intel_syntax noprefix
.code16
.set SERIAL_BASE, (0x3F8) # Base I/O
.set SERIAL_THR, (SERIAL_BASE+0) # Transmit Hold Register (w)
.set SERIAL_LSR, (SERIAL_BASE+5) # Line Status Register (r)
.set SERIAL_IS_THR_EMPTY, (0x20)
# Character to be sent in al
# Clobbers ah
.global serial_putc
serial_putc:
push dx
mov ah, al
mov dx, SERIAL_LSR
serial_putc_wait:
in al, dx
test al, SERIAL_IS_THR_EMPTY
jz serial_putc_wait
mov dx, SERIAL_THR
mov al, ah
out dx, al
pop dx
ret
# Character to be sent in al
# Carry flag is clear if nothing sent, set if character sent
# Clobbers ah
.global serial_putc_nowait
serial_putc_nowait:
push dx
mov ah, al
mov dx, SERIAL_LSR
in al, dx
test al, SERIAL_IS_THR_EMPTY
mov al, ah
jnz serial_putc_nowait_send
pop dx
clc
ret
serial_putc_nowait_send:
mov dx, SERIAL_THR
out dx, al
pop dx
stc
ret
To switch to 32-bit code generation, use .code32 directive.
You can compile the above using as source.s -o target.o.
The main differences are that dot (.) starts a directive, and # a comment; ; is just a separator like newline. All symbols are local by default, so you need to declare the global ones. Constants are defined using .set NAME, value instead of EQU.