Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use relative jumps?

Tags:

x86

assembly

nasm

I have the following questions regarding relative jumps:

  1. I understand that JMP SHORT <displacement> will jump to <displacement> bytes relatively to the current PC. Is that correct?
  2. Is it true that the assembler will generate an op code of a relative jump automatically? i.e. when I just write JMP <label>, if that label is located within 128 bytes away of the current PC, it will generate a relative jump?
  3. In case I do want to use JMP SHORT <displacement>, what is the right way to compute the displacement? By inspecting the listing file and calculating offsets?
like image 601
Ori Popowski Avatar asked Jun 22 '12 17:06

Ori Popowski


People also ask

What is a relative jump?

A relative jump jumps to an address specified relative to the current instruction pointer. The $E9 opcode is a relative jump with a 32 bit offset. Note that there are different jump opcodes for jumps with differently sized offsets.

What is the range of relative jumps?

Relative jumps can only jump forward 127 bytes or -128 in 16-bit code.

What is the difference between near jump and far jump?

Short jump—A near jump where the jump range is limited to –128 to +127 from the current EIP value. Far jump—A jump to an instruction located in a different segment than the current code segment but at the same privilege level, sometimes referred to as an intersegment jump.

What is an absolute jump?

absolute jump get the exact address of the target, and it's used when the code have static address space.


2 Answers

Suppose the assembler automatically used the short or the normal encoding. It may, on a first glance, seem OK to always switch to the short encoding if possible, but it's actually possible for that to make it so that some other branch has to be changed to the long encoding again.

For example (not tested or anything, just to get the idea):

  jmp _skip          ; relative offset depends on
               the size of "other code", which may include other jumps
  ; other code
_skip:

So you can't do a "forward" pass to determine the sizes - when you're at that jump, you don't yet know whether it's going to fit, because you haven't decided what to do with the other jumps yet.

Backwards then? (not tested or anything, just to get the idea)

  .fill 124
  jmp _somewhere     ; 2 bytes, or 5?
  jmp _quiteFarAway  ; relative offset is either 130 or 127
  .align 256
_quiteFarAway:

Nope, can't do a backwards pass either, when deciding the encoding for the jump to _quiteFarAway you don't yet know whether it's going to fit, because you haven't decided what to do with the other jumps yet.

Doing your point 2 is hard, and there are many different ways to solve that. Such taking an explicit "short" modifier, an explicit "long" modifier, making a safe guess and end up with the long version where it wasn't necessary in rare cases, etc.

like image 39
harold Avatar answered Sep 28 '22 06:09

harold


Each assembler (program) and each version of an assembler could choose to default to long or short. So I wouldnt look for a blanket statement that all assemblers default to one thing. If curious, try it and see what happens.

With x86 and variable length instructions it will be very tricky to simply code the displacement in, have to remind yourself to never touch the code between the jump and the target.

Yes, I start by letting the assembler code the instruction by using a label, then get the instruction set reference manual and a disassembly with addresses and figure out how the displacement is computed. If the assembler allows you set the displacement yourself that is likely an assembler specific thing and you need to know what units it may want that displacement. x86 is probably bytes, but fixed word length instruction sets you may have to give a displacment in units of instructions not bytes. or bytes not instructions, so I would use the displacement then disassemble again to see that it computed the correct instruction.

like image 56
old_timer Avatar answered Sep 28 '22 08:09

old_timer