How can I force the value of the relative offsets?
I know how to do: jmp label_name
Would like to do: jmp $0x01
Syntax issue... Nasm would use "$ + 5", (G)as would use ". + 5", and might need a "$" as well(?). I understand from the original tag, that we're using Nasm? Then "$ + 5" should be correct, but probably won't do what you want. The asm syntax would be "jmp target" (or "jmp $target" for Gas?), and you'll see the same thing in a disassembly... but look closely at the bytes being generated. The "jmp" opcode is followed by "distance to target", not "target"! If you want to code "distance to target", I think you'll need to resort to "db 0xE8" (or appropriate opcode) followed by "db (or dw or dd) 0x??" (".byte" or ".long" for Gas, I think). This probably isn't what you want to do. Re-think your code.
Best, Frank
GAS and NASM don't have syntax to set the rel8 or rel32 displacement directly, only the target address. (e.g. jmp +0
is interpreted as a jump to absolute address 0, or a syntax error).
You can encode it manually with .byte
/ .long
(GAS) or db
(NASM and most other non-GAS x86 assemblers). Note that the relative branch displacement is relative to the end of the branch instruction.
db 0xEB, 0x01 ; jmp short +1 over the 1-byte nop
nop
jump_target:
db 0xE9
dd -5 ; jmp near -5 also jump backwards to jump_target, i.e. to itself
(GAS would be identical but with .byte
and .long
instead of db
and dd
)
Or, use syntax for describing an address relative to the start of the line
jmp short $+3 ; rel8 = +1 NASM, forcing the jmp size to 2 bytes
jmp .+3 # rel8 = +1 GAS
How does $ work in NASM, exactly? shows an example of manually encoding a branch to reach a given target, subtracting $
(the current output position) from the target address, and adjusting for the length of the branch.
Here we need to take the branch length into account to get the the desired relative offset encoded, because our reference point for $ + x
is the start, not end of the instruction. We could put a label at the end:
jmp .rel_anchor + 123 ; rel8= +123 NASM local label
.rel_anchor:
jmp 1f + 123; 1: # GAS local label on the same line but a separate statement
1: # It might be more readable to put the label here.
This does actually work, we get eb 7b
from GAS.
Here is an example usage I made for fun.
BITS 32
segment .text
global _start
_start:
jmp tmp
PUSH 0x68732f
PUSH 0x6e69622f
LEA EBX,[ESP]
; ...
_jumpstop:
tmp equ ($ - _start)
That way once it is compiled it becomes
00000000 E90D000000 jmp 0x12
00000005 682F736800 push dword 0x68732f
0000000A 682F62696E push dword 0x6e69622f
0000000F 8D1C24 lea ebx,[esp]
So that the jump lands immediately after the lea ebx,[esp]
jmp . + 3
– johnchen902