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).