8
votes

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.

1
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
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
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, destMichael Petch
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
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

1 Answers

1
votes

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.