Intel Syntax: mov eax, 1 (instruction destination, source)
AT&T Syntax: movl $1, %eax (instruction source, destination)
The Intel syntax is pretty self explanatory. In the above example, the amount of data which is moved is inferred from the size of the register (32 bits in the case of eax). The addressing mode used is inferred from the operands themselves.
There are some quirks when it comes to the AT&T syntax. Firstly, notice the l
suffix at the end of the mov
instruction, this stands for long
and signifies 32 bits of data. Other instruction suffixes include
w
for a word (16 bits - not to be confused with the word size of your
CPU!), q
for a quad-word (64 bits) and b
for a single byte. Whilst not always required, typically you will see assembly code which uses AT&T syntax explicitly state the amount of data being operated on by the instruction.
More explicitness is required when it comes to the addressing mode used on the source and destination operand. $
signifies immediate
addressing, as in use the value in the instruction itself. In the above example, if it was written without this $
, direct
addressing would be used i.e. the CPU would try and fetch the value at memory address 1 (which will more than likely result in a segmentation fault). The %
signifies register
addressing, if you didn't include this in the above example eax
would be treated as a symbol
i.e. a labelled memory address, which would more than likely result in an undefined reference
at link time. So it is mandatory that you are explicit about the addressing mode used on both the source and destination operand.
The way memory operands are specified is also different:
Intel: [base register + index * size of index + offset]
AT&T: offset(base register, index, size of index)
The Intel syntax makes it a little more clear what calculation is taking place to find the memory address. With the AT&T syntax, the result is the same but you are expected to know the calculation taking place.
should, theoretically at least, produce the same binary
This is entirely dependent on your toolchain.
what are the reasons to favour one or the other?
Personal preference of course, in my opinion it comes down to which syntax you feel more comfortable with when addressing memory. Do you prefer the forced explicitness of the AT&T syntax? Or do you prefer your assembler figuring out this low level minutia for you?
Is it command line options? Macros? Non-mnemonic keywords?
This has to do with the assembler (GAS, NASM) itself. Again, personal preference.