3
votes

What is the order of operands in x86-64 assembly?: instruction destination, source Or: instruction source, destination

I have three books and two different approaches!

1
Actually, it can vary depending on what assembler you use. There are two common standards Intel and AT&T. There are frequent debates over which one is "better."David Wohlferd
For AT&T for instance it is cmd source, dest while with Intel it is cmd dest, source so it is assembler dependent.David C. Rankin
@DavidWohlferd: I think the main debate is usually whether AT&T syntax is usable / bearable at all. I've seen very few claims that it's better. The most that people usually claim is that it's not worse and you can get used to it, at least compared to a nice consistent assembler like NASM. It's pretty hard to defend a syntax that literally has design bugs (with fsubr vs. fsub being reversed for some register-register operands. sourceware.org/binutils/docs/as/i386_002dBugs.html). Other than for x87, I don't have a problem with it after getting my brain into AT&T mode.Peter Cordes

1 Answers

5
votes

It depends on the syntax of an assembler. Mostly we have two choices: Intel and AT&T syntaxes.

There are multiple flavours of Intel syntax, the major ones being NASM (mov dword [symbol_name], 1) and MASM (including GAS's .intel_syntax noprefix mode which many GNU and Unix tools can use.) See https://stackoverflow.com/tags/intel-syntax/info for details on the differences and telling them apart.

Intel syntax example (from objdump disassembly, so this is GNU .intel_syntax, with a couple examples added in):

push   rbp         # comment character can be # (GAS) or ; MASM/NASM
mov    rbp,rsp
mov    DWORD PTR [rbp-0x4],edi
mov    DWORD PTR [rbp-0x8],esi
mov    edx,DWORD PTR [rbp-0x4]
mov    eax,DWORD PTR [rbp-0x8]
add    eax,edx
pop    rbp
ret

add    dword ptr [rdi], 1    # size specifier mandatory if neither operand is a reg
imul   ecx, [rdi + rax*4 + 20], 12345

There's only one flavour of AT&T syntax (https://stackoverflow.com/tags/att/info):

push   %rbp                 # comment character is always #
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    -0x4(%rbp),%edx
mov    -0x8(%rbp),%eax
add    %edx,%eax
pop    %rbp
retq

addl  $1, (%rdi)      # size suffix b/w/l/q used to indicate operand-size if neither operand is a register

# with more than 2 operands, reverse the whole list
imul   $12345, 20(%rdi, %rax, 4), %ecx 

AT&T syntax is native to Unix systems. Usually, decompilers have flags to control a type of output syntax. For example objdump has -Mintel flag, gdb has set disassembly-flavor intel option.

Also, take a look at this useful site on which you can quickly see assembler output without noise Compiler Explorer


Beware that AT&T syntax has a design bug for x87 non-commutative FP instructions like fsub and fsubr with register operands: see the manual: https://sourceware.org/binutils/docs/as/i386_002dBugs.html