(Taken from a
post in the MegaTokyo OS Development forum, with additional credit given below)
The AT&T syntax (as understood by
GAS, the GNU assembler) is the standard syntax on most non-Intel platforms, but remains rare among x86 assembly programmers (where the Intel syntax is understood by virtually every assembler). However, AT&T is what you need for InlineAssembly, and it is what objdump will provide you with when debugging your kernel.
You can switch to intel syntax mode in the inline assembler with a pseudo op, and switch back at the end of the block. See also
https://mirbsd.bsdadvocacy.org:8890/cvs.cgi/src/share/man/man7/gas-intel-howto.7 for a small writeup on gas/intel for people who know gas/att or {t,n}asm/intel. Feedback and suggestions welcome.
-- MirAbileThat link you gave works on a port that's blocked by some firewalls. Is there any chance you'd share the contents in form of a Wiki page for ease of reference?
-- MartinBauteNew page with the contents on it, note: it's troff/groff source: GasIntelHowtoMirror
-- DasCandy
There are some substantial differences between the AT&T syntax and the Intel sytnax, which a programmer intending to use the GNU tools should be aware of. Here are a few key things to look for:
- case sensitive. "MOVL" is not the same as "movl".
- numerical base is expressed as in C: 1 for decimal, 01 for octal, 0x01 for hex. (The Intel postfix-h syntax is not supported.)
- escapes. Special characters are written as C-style escapes (\n, \", \#, \\, ...).
- comments can be either C-style ("/* ... */") or shell style ("#").
- directives begin with a period (".align 4" to align on a doubleword boundary, ".word 0x1234" is the equivalent of "DW 1234h").
- strings are defined using special directives, ".ascii" and ".asciz" (the latter appending a '\0' to the string). Example: msg: .ascii "Hello, World!\n"
- current location address in the assembly code is indicated by a period (".", equivalent to Intel syntax "$").
- initializing memory is done with .fill (roughly equivalent to Intel syntax 'times db'). Example: .fill 0x1fe - (. - START) , 1, 0 (where '1' is the size fill mask in bytes and START is a label marking the entry point of the code) is equal to Intel syntax times 1FEh - ($-$$) db 0. (The .skip and .space directives can be used in a similar manner.)
- the code counter can be set multiple times, using the .org directive (as in .org 0x1fe + START, where START is a label marking the entry point of the code. The location-assignment directive, '.=', can be used in the same manner.
- 16/32 bit code can be generated by stating .code16 or .code32 (equivalent to Intel syntax [BITS 16] and [BITS 32], respectively).
- target CPU is set with the .arch directive. It is a Good Idea to set it, even if you are sure that the default is 'i386'.
- label declarations always end in a colon.
- a new identifier appearing at the beginning of a line, and not ending in a colon, is assumed to be part of an equivalence statement, and must be followed by an equals sign and an assigned value. Example: FOO = 0xF00
- end of instruction is designated either by a newline or with a semi-colon; the latter is primarily seen in macros, to allow multiple lines of code.
- line continuation is done as in C, with a backslash ('\') as last character in a line. This also is mostly used in macros.
- registers are always prefixed with a percent sign: %eax, %cs, %esp, etc.
- source, destination: move, load, store, and similar operations are always 'source, destination', which is opposite of most (but not all) Intel instructions. Thus, "movl %eax, %ebx" moves the value of %eax into %ebx. This is the part that seems to confuse people the most, but in fact, the AT&T syntax is more consistent on this point than the Intel syntax is.
- operand size suffixes are always appended to instructions (with the exception of ljmp, lcall, and lret on the x86): movb for "move byte", movw for "move word", movl for "move long", etc.
- direct-address operands are not prefixed. Thus, "movl foo, %eax" moves the contents of memory location "foo" into %eax.
- immediate operands are prefixed with a dollar sign ($): "pushl $4" pushes 0x00000004 onto the stack. This applies to labels as well: "movl $foo, %eax" moves the value of the label foo (that is, the address of variable foo) into %eax.
- indexed / indirect operands are used in the format segment:displacement (base, index, scale), like so: movl %eax, %ss:8(%ebp, 2, 3) (which is equivalent to Intel syntax mov dword [ss:ebp + 2 * 3 + 8], eax, that is, it moves the value of %eax to offset (%ebp + (2 *3) + 8) in segment %ss). Any of the five operands of an indirect address may be omitted.
- relative (short addressing) is used by default in jump and call instructions. To use absolute (near) addressing, the operand must be prefixed with an asterisk (*).
- far jumps / calls / returns must use the special 'ljmp', 'lcall' and 'lret' instructions.
Macros
The built-in macro system has the following syntax:
.macro <name> <args> <operations> .endm
Example:
.macro write string movw string, %si call printstr .endm
This would be equivalent to the NASM macro:
%macro write 1 mov si, %1 call printstr %endmacro
Additionally, the cpp and m4 macro preprocessors are often used for macro handling.

https://mirbsd.bsdadvocacy.org:8890/cvs.cgi/src/share/man/man7/gas-intel-howto.7