I've been struggling a lot with the error "jmp out of range", a lot of times I need to run a subrutine from different parts of my code as I would a function in C++.
I got to a point that both ends on my code need to jump to the same place and there is just no way for both to get there.
What is the solution for this?
Also I noticed that
PRINT 'something'
Seems to occupy more "space" than using:
CALL PTHIS
DB 13, 10, 'something', 0
(If I put a PRINT between two jumps I get jump out of range but if I replace it with a PTHIS there is no problem)
Why is this?
The problem with the conditional jump instructions in 16-bit assembler is that they're limited to +127 or -128 bytes for the offset.
386 introduced the jcc rel16
encoding that is available in 16-bit mode, but only on 386 and later. Different assemblers have different options for enabling 386 instructions in 16-bit code
Some also have options to automatically do what's described below: conditional jcc rel8
over a jmp rel16
. For example, TASM has /jJUMPS
.
Let's say you have this:
cmp al, '1'
jnz ItsNot1
; lots of code here
ItsNot1:
If you get a jump out of range error you can re-code it like this:
cmp al, '1'
jz Its1
jmp ItsNot1
Its1:
; lots of code here
ItsNot1:
All I did there is change the sense of the comparison and jump around the unconditional jump that takes you to the alternate code path.
It gets annoying sometimes if you have lots of conditional jumps. You'll re-code one of those and it'll trigger another. And then you refactor the code and discover some of those mangled conditionals can go away. Typically I don't worry about it unless I'm seriously concerned about code size.
Some assemblers have a switch that will do automatic jump sizing for you so that you can always code the conditional jumps and they'll do the jump-around-conditional-jump trick automatically.
Most likely the difference between
PRINT 'something'
and
call PTHIS
db 13, 10, 'something'
Is that the first one is a macro that expands to the full code for printing something, plus the string you want to print. The second is a simple call
instruction (3 bytes), plus the string. Or, in C++ terms, the PRINT
macro is like an inline function, and the call PTHIS
is a normal (not inlined) function call.
Sometimes you have to negate your test and make the branch just jump ahead a bit while the fall through is an unconditional jump to your out of range destination.
来源:https://stackoverflow.com/questions/17307834/jump-out-of-range-solutions-and-how-different-instructions-affect-range