Why was the AT&T assembly syntax designed this way

assemblyhistoryprogramming-languagessyntax

The AT&T assembly syntax, often called the GAS syntax, keeps surprising me. For example, its parameter order:

mov $100,%eax /* Destination after source */

This just seems so counter-intuitive! Nearly all programming languages (and the good old mathematical notation) go the other way around: destination before source, like this:

int a = 100;   /* Destination before source (C-style) */
a := 100       // Destination before source (Pascal-style)
mov eax,100    ;  Destination before source (Intel assembly syntax)

There are other points, for example, sigils… The %-s before every register and the $ before every constant literal (except for those used as the fourth operand in the very strange-looking effective addressing syntax) mightily clutter up the code, when it would have been trivial to avoid them. What is, or was, their advantage?

Best Answer

I do not know what the deal is with sigils, other than perhaps to scare the uninitiated and to annoy those wise enough to know that they could have very easily been missing. Hopefully, another answerer will have more insight on this. (As ratchet freak mentioned in the comments, it was probably done this way in order to simplify the parser, which perhaps made sense back in those days when computing resources were meager.)

Now, as far as operand order is concerned, there are arguments that can be made for it and against it, although the arguments against it win.

It can be argued that GAS syntax is slightly more consistent than, say, Intel syntax, because when thinking of "moving" stuff, something gets moved from one place to another. When reading the code out loud, it makes sense to say "move this value to that register", but it does not make sense to say "move this register from that value".

By contrast, other assembly languages (Zilog, etc.) call these instructions "ld", which stands for "load", where it makes sense to have destination before source, because something is being loaded with a value. This has the additional benefit of following the standard operand order of mathematics, but it can be argued that this is not necessary, because assembly language programming is not mathematics, and there is no need to pretend that it is. (Similar things should look similar, and different things should look different.)

Of course, the argument for GAS syntax is lost if you consider that "move" is the wrong choice of verb in the first place, because the source operand does not lose its contents as a result of the "mov" operation: the bits do not really get moved, they are copied.

And then things get complicated even more by the fact that the Intel x86 instruction set includes instructions such as "lea" (load effective address) which go with the "load" verb instead of the "move" verb, in which case the GAS operand order is just plain wrong from whichever way you look at it.

Bottom line: it is just a matter of convention, so whoever builds the CPU gets to pick their preferred convention, and then whoever writes an assembler which is not required to be compatible with preexisting assemblers may, if they so please, come up with their own convention. The first GAS assembler was probably written for some architecture in which the convention was source-operand-first, and then in subsequent ports of the assembler to other architectures the authors decided that having to change the instruction set and the register set was enough of a burden already, so they probably thought that it would be cool to at least stick with the same operand order.