8

Here is some assembly code in Intel syntax:

// Jump to done if rsi >= rax.
cmp rsi, rax
jae done

This makes sense to my brain: you jump if rsi is "above or equal to" rax, matching the order of arguments in the cmp instruction. Compare this to the GNU syntax:

// Jump to done if rsi >= rax.
cmp %rax, %rsi
jae done

This hurts my brain every time. It doesn't help that when I come to this fresh after awhile not writing assembly code I go to look up the semantics of cmp and jae in the Intel manual and find that it's all stated in terms of "first" and "second" operand, which doesn't match what I'm seeing on the screen in front of me.

End complaining. My questions:

  1. Is there some other way to express cmp or jae to the GNU assembler so that the order of operands to cmp matches the logical comparison referred to by jae?

  2. Assuming the answer to (1) is no, does anybody have a good way for me to look at this so that I can remember how it works next time? Anything better than "GNU does it backwards"?

Note that I'm not asking how to use Intel syntax with the GNU assembler; I'm aware that's possible. I'm working in an existing GNU syntax codebase, and am asking for some mnemonic or other way to help me keep this straight in my head.

jacobsa
  • 5,719
  • 1
  • 28
  • 60
  • 8
    More modern GNU assemblers support this directive `.intel_syntax noprefix`. Place it at the top of your assembler files and the contents will be interpreted as intel syntax without the need for the % prefix on registers. As for normal GNU assembler AT&T syntax the rule is simple - source is on the left, destination on the right. – Michael Petch Jan 15 '16 at 05:19
  • Thanks for the tip on the directive; that's really great and I'll try to get it through a code review. But please help me understand the rule: in what sense is there a source and a destination in `cmp %rax, %rsi`? I know that `cmp` is implemented as a subtraction, but it's rather hard to keep straight in my head. I'm just looking for a mnemonic. – jacobsa Jan 15 '16 at 10:00
  • 1
    In Intel syntax with multiple operands the destination operand is on the left and the source operand is on the right. In AT&T syntax (default for GNU assembler) the source operand is on the left, and the destination operand is on the right. This holds true for all the multi operand instructions. _SUB_ and _CMP_ are dest - src. In intel syntax that is *mnemonic dest, src* AT&T syntax is *mnemonic src, dest* – Michael Petch Jan 15 '16 at 10:07
  • 1
    Right, I understand all that. The problem is that `jae` doesn't say "jump if you didn't have to carry when subtracting src from dst"; it says "jump if above or equal". It's hard to remember that it means jump if _dst_ is above or equal _src_, and not the other way around. Another way to solve my problem: is there an alias that looks like "jump if carry flag not set"? – jacobsa Jan 15 '16 at 21:40
  • jump if carry flag not set is `jnc` . Intel and AT&T syntax don't alter the semantics of the machine language instructions. They just reverse where operands appear at the assembly language level. Both CMP and SUB both do DST-SRC (sub stores in DST of course). In Intel syntax it is the DST on the left. In AT&T it is reversed (DST on the right). If you are use to Intel then you just have to remember to swap the operand around when using AT&T. – Michael Petch Jan 15 '16 at 21:42
  • Possible duplicate of [Questions about AT&T x86 Syntax design](http://stackoverflow.com/questions/4193827/questions-about-att-x86-syntax-design) – Johan Aug 29 '16 at 00:04
  • Possible duplicate of [Can I use Intel syntax of x86 assembly with GCC?](http://stackoverflow.com/questions/9347909/can-i-use-intel-syntax-of-x86-assembly-with-gcc) – Johan Feb 06 '17 at 14:44
  • Intel broke my brain from the start. Other assemblers have move src to dest or load dest from src. Intel had load src into dest. ARGH! (That was the point I decided to learn C). – Mike Feb 07 '17 at 22:40
  • Related: [Regarding cmp / jg, jle, etc in AT&T syntax assembly](https://stackoverflow.com/q/29574147) – Peter Cordes Aug 28 '20 at 04:19

1 Answers1

1

In GAS you can use .intel_syntax noprefix to get the syntax you're more familiar with, but you can't just swap them around in AT&T syntax.

I'd say keep in mind that in Intel syntax mov x,y means 'make x equal to y' whereas in AT&T syntax it's 'copy x into y', once you have that convention down expand it to other instructions you come across.

0x777C
  • 993
  • 7
  • 21
  • Right, the story makes sense for `mov`. My question is: how the hell does it make sense for `cmp` followed by `jae`? – jacobsa May 18 '19 at 07:50
  • It doesn't, but you use the story to remember the convention. If you want you can read operands from right to left. – 0x777C May 18 '19 at 10:32
  • Thanks, "read arguments right to left and treat `mov bar, foo` as make `foo` equal to `bar`" is the closest I've come to this making any sense. – jacobsa May 19 '19 at 04:47