If I do something like (dummy example):
jmp 1f
1: ret
on gcc/clang it generates a short relative jump because the label is near.
I'm curious, is it possible to force a JMP rel32
regardless of the label's distance?
Michael Petch's suggestion in the comments to hardcode jmpq
via its bytecode 0xe9
unfortunately only works with local labels, but I would like something that works with global linker-resolved labels too.
Since my real goal is to paste a constant-length jump instruction via a macro, I can also make do with stuff like jmp 1: /*definitely short*/; 1: jmp /*short or long*/ actual_target_with_unclear_distance;
, relying on the first jump being definitely short, but using just one definitely-long jump would be shorter and cleaner if there's any way to achieve it.
According to the GAS manual, section 9.16.8 "Jump instructions are always optimized to use the smallest possible displacements". This seems to imply there is no manual way to override it. There is an addr32 instruction prefix in 9.16.6 but it is only allowed in
.code16
. I cannot seem to find an option that would control the size ofjmp
offset in any "official" source.However, according to this source marking the label you jump to as global will make the
jmp
instruction use arel32
offset. I only managed to reproduce the behavior using clang though, GCC does not seem to work. Additionally, i cannot seem to find any more credible source for this behavior than the mentioned 15-year-old archived mailing list reply so i would not exactly call it "reliable". I assume it might go away unnoticed with some future update to clang/llvm-as.For an example, following file
test_asm.s
:compiled with
clang test_asm.s
on my machine results in:Meanwhile, after removing the
.global lab
line the result is:For a reliable, although a tedious solution, you can always manually encode the
jmp
instruction to bytes and then input them using the.byte
directive in place of thejmp <operand>
mnemonic, as pointed out in the comments.