-
Notifications
You must be signed in to change notification settings - Fork 29
Intel syntax
The AT&T syntax is a horrible mistake. The decision to put up with that piece of evilness is even more horrible.
- xmm0 = xmm1 * xmm2 + xmm3
- should read
vfmaddpd xmm0, xmm1, xmm2, xmm3
, - instead of
vfmaddpd %xmm3, %xmm2, %xmm1, %xmm0
.
- should read
- IF eax IS GREATER THAN ecx THEN GO TO label
- should read
cmp eax, ecx; jg label
, - instead of
cmpl %ecx, %eax; jg label
which Plan 9 dogs seem to have been aware of, but they refuse to correct all the others.
- should read
- st(3) -= st
- should read
fsub st(3), st
, - instead of
fsubr %st, %st(3)
which has the bug only because of its retardness about order of operands.
- should read
- eax = ecx + edx * 2 + 42
- should read
lea eax, DWORD PTR [rcx + rdx * 2 + 42]
, - instead of
leal 42(%rcx,%rdx,2), %eax
.
- should read
The wrong order of operands is inexcusable and shameful, seen on x86 and m68k but nowhere else. Even some more awful assembly languages prefer the natural destination-source order, such as PowerPC.
If the AT&T syntax was better, why do addps
etc. have no operand size suffixes like movl
etc. do? And why is movl 0x1234,%eax
not movl (0x1234),%eax
? And why is jmpq *%rax
not jmpq (%rax)
? And why is there not an AT&T clone for AVR, ARM, MIPS, RISC-V, etc.?
Those are just random choices that happen to be there, work by accident, and probably nobody wants to fix either because people are used to it or they are incompetent or they just don't care, whatever. It was Plan 9 dogs who couldn't stop making mistakes and earned consequent infamy for themselves.
And Why no one should use the AT&T syntax ever, for any reason, under any circumstances:
Everybody uses Intel! And I mean, everybody. Every assembler, every disassembler, every reverse-engineering tool, every debugger. Documentation from Intel and AMD’s official manuals, as well as most of the unofficial ones. Inline assemblers for the D, Rust, and Zig reference compilers, and Microsoft’s C compiler.
Everybody except for GCC and the GNU toolchain (and its clones, Clang and TCC), who just have to be different.8 All the cool kids are doing it, why won’t you? Even assemblers for other architectures use syntax that looks a lot like Intel syntax. Even the Plan 9 assembler, made by many of the same AT&T employees who made Unix and the original AT&T assembler, walks back on some of AT&T’s horrible mistakes (though unfortunately none of the important ones).9
When it comes to inline assembly, for example:
void*
fast_tls_get_value(uint32_t offset, uint32_t index)
{
void* value;
__asm__ ("mov %0, QWORD PTR gs:[%1 + %2 * 8]" : "=r"(value) : "re"(offset), "re"(index));
return value;
}
It does not matter what the heck you put in []
. No matter whether the argument is a register or a constant, it's always correct: https://gcc.godbolt.org/z/bnsMT1jdf
But if it was AT&T syntax, they would not allow you to put symbols or contants in ()
, and they would not allow you to put registers outside ()
. Then suddenly, there is no uniform template for this function; it has to be one of:
// "r" for register; "e" for constant
// \-------------------v------------v
__asm__ ("movq %%gs: (%1,%2,8), %0" : "=r"(value) : "r"(offset), "r"(index));
__asm__ ("movq %%gs: %c1(,%2,8), %0" : "=r"(value) : "e"(offset), "r"(index));
__asm__ ("movq %%gs:(%1,,%c2*8), %0" : "=r"(value) : "r"(offset), "e"(index));
__asm__ ("movq %%gs: %c1+%c2*8 , %0" : "=r"(value) : "e"(offset), "e"(index));
Be advised, constants can be a result of optimization! Then how would you know which is the correct one to use? That's a question for AT&T dogs to answer.
alias gcc='gcc -masm=intel'
alias g++='g++ -masm=intel'
alias clang='clang -masm=intel'
alias clang++='clang++ -masm=intel'
set disassembly-flavor intel
tui new-layout hsplit {-horizontal src 1 asm 1 } 2 cmd 1
layout hsplit
focus cmd
alias objdump='objdump -Mintel'
OBJDUMP='objdump -Mintel'
OBJDUMP='objdump -Mintel'
AC_CHECK_DECL([__i386__], AS_VAR_SET([host_asm_opt], ["-masm=intel -msse2 -mfpmath=sse"]))
AC_CHECK_DECL([__amd64__], AS_VAR_SET([host_asm_opt], ["-masm=intel"]))
## ...
AC_SUBST([host_asm_opt])
AM_CPPFLAGS = @host_asm_opt@
if meson.get_compiler('c').has_argument('-masm=intel')
add_project_arguments('-masm=intel', language: [ 'c', 'cpp' ])
endif