There are two syntaxes/notations for x86 assembly:
- Intel notation, which puts destinations first.
- GNU or AT&T notation, which puts destinations last.
So the C code a = b would correspond to the following assembly patterns:
- Intel:
mov a, b - GNU:
mov %b, %a (move b to a)
Similarly, for a subtraction a = a - b:
- Intel:
sub a, b - GNU:
sub %b, %a (subtract b from a)
As a side effect, sub will set flags corresponding to the result being equal/greater/less than zero.
The cmp is equivalent to a sub instruction, except that it discards the result – it has no destination in the typical sense. However, the GNU notation retains the sub argument order, improving consistency in the syntax.
The conditional jump instructions like jl do not care about operand order. They only look up the value of flags, which might be set by instructions like cmp, test, or sub.
Please also note that assembly code is a human-oriented programming language, not machine code. A line like cmp $0, %eax doesn't correspond directly to an actual "cmp" instruction, instead the assembler selects an appropriate encoding. For example, x86 cmp has about 20 different encoding schemas depending on operand sizes, whether one operand is an immediate value, or whether the register used is eax/rax. The assembly syntax can also change operand order when appropriate.