0

For an indirect jump to the address stored in L + 8 in 64-bit mode,

nasm accepts,

jmp [L + 8]
jmp qword [L + 8]

GNU as accepts,

jmp [L + 8]
jmp qword ptr [L + 8]

and also,

jmp [[L + 8]]
jmp [qword ptr [L + 8]]

even more,

jmp qword ptr [offset L + 8]
jmp [qword ptr [offset L + 8]]

but not,

jmp [offset L + 8]
jmp [[offset L + 8]]

I'm very confused about what effects the brackets, qword ptr and offset are having in those statements.

I know the basics that GAS treats L as same as [L], and you have to put offset to use L as a constant memory address, but this doesn't explain why sometimes it's okay to omit offset and sometimes you must omit offset, and why it is okay to put additional brackets.

Could you clarify the syntax used for indirect jumps in GAS Intel syntax?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
xiver77
  • 2,162
  • 1
  • 2
  • 12
  • 2
    The fact that GAS accepts some crazy syntax is just a side effect of a less-than-perfect parser. Do not use double brackets, or the `offset` keyword. In any case, use a disassembler if you are curious what the assembler emits for the crazy forms. – Jester Feb 01 '22 at 22:52
  • 1
    Should be no different from addressing modes in other contexts, like `mov rcx, [L + 8]`. (Note that you should use `[RIP + L + 8]` because RIP-relative addressing is more efficient than absolute, even when absolute is possible.) – Peter Cordes Feb 02 '22 at 01:12
  • 1
    oh, I guess there is one difference: `jmp L` would be a different instruction, so you do always need brackets or something else to disambiguate from a relative direct jump. But otherwise it's just a normal addressing mode, I think. As Jester says, GAS's parser is not very strict. e.g. `mov $'abcd', %eax` breaks the parser in interesting and exciting ways, instead of working anything like NASM `mov eax, 'abcd'`. It seems GAS only cares about the opening quote, not a close quote. – Peter Cordes Feb 02 '22 at 02:46
  • @PeterCordes I'm a bit confused by your comment about relative addressing. Is it still more efficient when I'm not compiling to a PIE executable? Also with relative addressing I have to put additional `lea`s to add a variable index. – xiver77 Feb 02 '22 at 17:06
  • `[RIP + rel32]` is more efficient than `[disp32]` with no GP registers. If you want to use it with a GP register, `[base + disp32]` is just as efficient, and of course saves an LEA. I meant using relative addressing for access to static storage, not writing fully position-independent code. See [Why are global variables in x86-64 accessed relative to the instruction pointer?](https://stackoverflow.com/q/56262889) / [Why use RIP-relative addressing in NASM?](https://stackoverflow.com/a/34034877) / [How to load address of function or label into register](https://stackoverflow.com/q/57212012) – Peter Cordes Feb 03 '22 at 01:44

0 Answers0