1

How can I force the value of the relative offsets?

I know how to do: jmp label_name

Would like to do: jmp $0x01

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Mathew Kurian
  • 5,949
  • 5
  • 46
  • 73

4 Answers4

4

You can use a relative jump like

jmp $+5

It relative to the start of the jump.

Daniel
  • 30,896
  • 18
  • 85
  • 139
2

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

Frank Kotler
  • 1,462
  • 1
  • 8
  • 4
1

Here is an example usage I made for fun. (Uses NASM)

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]

skyfire
  • 227
  • 1
  • 6
  • 1
    Normally you'd use `mov ebx, esp`. It's more efficient than `lea` to copy a register, and for `esp` it's actually shorter. – Peter Cordes Nov 09 '20 at 03:01
1

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 $ + xis 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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Last paragraph seems to end midsentence. – ecm Nov 12 '20 at 21:39
  • 1
    @ecm: I had this half written when the power went out. Tabbed over to it and whipped it into shape to post and close the tab while on UPS power, but was in too much hurry to check it. :P (And then tabbed away from this and didn't get back to it for a month :P) – Peter Cordes Dec 16 '20 at 04:00