We will see how Intel syntax can be used instead of AT&T with GAS, and talk about the differences.

In previous post, we compiled a few lines of assembly, using GAS (GNU Assembler) in Linux.

[ Check out all posts in “low-level” series here. ]

GAS, by default, uses the AT&T syntax. There are two major syntax branches for x86: AT&T, and Intel.

Let’s see how the same code looks in Intel syntax.1

Here is the Wikipedia entry describing the main differences.

I haven’t written enough assembly to have a preference. I more often read assembly for debugging, rather than writing it. So I find it beneficial to roughly understand both syntaxes.

GAS supports both. Here is an SO answer that describes how to use Intel syntax, both in assembly and C/C++ contexts. There is also a nice set of links in the “Related” section.

In order to reuse the makefile from the previous post, I will use the .intel_syntax noprefix directive for enabling Intel sytax in GAS.

x86 version of the code:

    .intel_syntax noprefix
    .section .data

    .section .text
    .global _start
_start:
    mov eax, 1
    mov ebx, 0
    int 0x80

So movl $1, %eax becomes mov eax, 1.

The changes we see in this one line:

  • Destination (eax) before source (1).
  • No % prefix (sigil) to register name, and no $ prefix to the integer literal.
  • No l (long or dword) suffix in the mnemonic. Parameter size is derived from the register name instead: eax. ( See this and this for details on x86 register names.)

There are other syntax differences (effective addresses etc.) that don’t show up in this minimal example.

And the x64 version of the code:

    .intel_syntax noprefix
    .section .data

    .section .text
    .global _start
_start:
    mov rax, 60
    mov rdi, 0
    syscall
  1. I am not very experienced in assembly. If you find errors, please report in the blog’s Issues page