x86 (both 32- and 64-bit) has two alternative syntaxes available for it. Some assemblers can only work with one or the other, while a few can work with both. We will primarily use the Intel syntax in this course, as it is what the textbook uses, but you should be aware of the AT&T syntax, as it is standard on Linux and thus many online resources use it.

This table summarizes the main differences between Intel and AT&T syntax:

Intel AT&T
Comments ; //
Instructions Untagged add Tagged with operand sizes: addq
Registers eax, ebx, etc. %eax,%ebx, etc.
Immediates 0x100 $0x100
Indirect [eax] (%eax)
General indirect [base + reg + reg * scale + displacement] displacement(reg, reg, scale)

Note that in the generalized indirect format, the Intel syntax will computer base + displacement for you, as the opcodes really only allow a single immediate displacement. In the AT&T syntax, you have to do this yourself, using the result of the sum as the third value in the parenthesis.

The main difference between Intel and AT&T syntax is that Intel leaves the sizes of the instruction operands implicit, while AT&T makes them explicit, by appending suffixes to the instruction name. An example is the add instruction which adds two values together:

add eax, ebx ;

As given, in Intel syntax, this adds two 32-bit registers together (both eax and ebx are 32-bit), and stores the result into eax. (Intel instructions have the destination register first, and the source register second.) Because both source and destination are 32-bit, the assembler knows that it needs to emit at 32-bit add instruction. In AT&T syntax, the same instruction would be

addq %ebx, %eax ;

Register names in AT&T syntax are prefixed with %, and the order is swapped, but the biggest difference is the q suffix on the add instruction. q is short for “quadword”, i.e., 32-bit value. The suffix is required to tell the assembler the size of the operands; it will not infer the correct instruction to use just from the register sizes.

Instructions that can mix operands of different sizes will have two (or sometimes three) suffixes. For example, to add the low 16 bits of ebx into eax, we would do

add eax, bx ;

in Intel, but in AT&T this would be

addzqd %bx, %eax ;

where d stands for “doubleword”. The z specifies that this is an unsigned addition (zero extension). If we wanted signed addition, we would use s (sign extension).