1

I noticed that, unlike GNU as (GAS), the LLVM-internal assembler, which is used by Rust, doesn't allow using jmp %rax. The compiler errors with "mnemonic without a size suffix". If I try adding a size suffix like this jmpq %rax, it doesn't work either.

Minimal reproducer:

core::arch::global_asm!(
        "foo:",
        "mov $ffffffff88000000, %rax",
        "jmp %rax"
    , options(att_syntax));

fn main() {
}

When I compile this assembly code with GAS, objdump shows jmpq *%rax.

phip1611
  • 5,460
  • 4
  • 30
  • 57
  • It's not totally "fine" in GAS, it warns about an indirect jump used without `*`. As explained in [What does an asterisk \* before an address mean in x86-64 AT&T assembly?](https://stackoverflow.com/q/9223756), it disambiguates `jmp foo` (RIP = foo, `jmp rel32`) from `jmp *foo` (absolute addressing mode for a memory-indirect jump) – Peter Cordes Dec 11 '22 at 21:35
  • It would probably be good if LLVM's error message was more helpful, suggesting you might have meant to use a `*`. – Peter Cordes Dec 11 '22 at 21:47

1 Answers1

2

There are subtle differences between GAS and LLVM's internal assembler. GAS seems to allow more "sloppiness" and LLVM is more precisely.

I don't know what's the meaning of it, but changing the line to jmp *%rax (with *) solves the issue.

phip1611
  • 5,460
  • 4
  • 30
  • 57
  • 2
    The `*` distinguishes direct from indirect jumps by making the jump look like it would [on a PDP-11](https://stackoverflow.com/a/42250270/417501). – fuz Dec 11 '22 at 21:46