I have the following questions regarding relative jumps:
JMP SHORT <displacement>
will jump to <displacement>
bytes relatively to the current PC. Is that correct?JMP <label>
, if that label is located within 128 bytes away of the current PC, it will generate a relative jump?JMP SHORT <displacement>
, what is the right way to compute the displacement? By inspecting the listing file and calculating offsets?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.
Relative jumps can only jump forward 127 bytes or -128 in 16-bit code.
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.
absolute jump get the exact address of the target, and it's used when the code have static address space.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With