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?
CodePudding user response:
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 of jmp
offset in any "official" source.
However, according to this source marking the label you jump to as global will make the jmp
instruction use a rel32
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
:
.global main
main:
jmp lab
.global lab
lab: ret
compiled with clang test_asm.s
on my machine results in:
000000000000111c <main>:
111c: e9 00 00 00 00 jmp 1121 <lab>
0000000000001121 <lab>:
1121: c3 ret
Meanwhile, after removing the .global lab
line the result is:
000000000000111c <main>:
111c: eb 00 jmp 111e <lab>
000000000000111e <lab>:
111e: c3 ret
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 the jmp <operand>
mnemonic, as pointed out in the comments.