Jumping back 1000 lines

2019-09-21 21:38发布

问题:

I was trying to make a code, that when you're at the very end, it will ask you if you want to try again. If you press 'y', then it will jump back a 1000 lines, right at the beginning of the program.

Well obviously, it didn't work out, as I got the error "jump relative out of range". So I made jumps every 50 lines, having a total of 20 jumps, like

start:
.
s20: jmp start
.
.
.
s2: jmp s3
.
s1: jmp s2
.
jmp s1

Now after doing that, I ran the program, and when I pressed 'y', TASM kind of froze. It was just displaying the last screen, with the 'y' input, and a blinking _. I couldn't press a character anymore.

回答1:

In x86 you don't need a cascading sequence of jumps, since jmp can jump over the whole segment. Just a conditional jump like jne has a limited range. So you can change an errorneous conditional jump to a combination of an unconditional near jump and a conditional short jump:

As an example, change

.MODEL small
.STACK 1000h

.CODE
main:

top:
    mov ax, 1
    jmp bottom


ORG 1000h               ; A big block between top and bottom

bottom:
    cmp ax, 0

    je top              ; **Error** Relative jump out of range by 0F85h bytes

    mov ax, 4C00h       ; Return 0
    int 21h

END main

to

.MODEL small
.STACK 1000h

.CODE
main:

top:
    mov ax, 1
    jmp bottom


ORG 1000h               ; A big block between top and bottom

bottom:
    cmp ax, 0

    jne skip            ; Short conditional jump
    jmp top             ; Near unconditional jump
    skip:

    mov ax, 4C00h       ; Return 0
    int 21h

END main

TASM can do that automagically for you. Place a "JUMPS" at the beginning (or where you need it) of the file:

JUMPS

.MODEL small
.STACK 1000h

.CODE
main:

top:
    mov ax, 1
    jmp bottom


ORG 1000h               ; A big block between top and bottom

bottom:
    cmp ax, 0

    je top              ; TASM will change this line to a JNE-JMP combination

    mov ax, 4C00h       ; Return 0
    int 21h

END main

The 80386 instruction set (ISA) has an instruction for a near conditional jump. If your emulator supports the 80386 ISA (DOSBox does), you can tell TASM to use it. Insert a .386 directive:

.MODEL small
.386                    ; Use 80386 instruction set
.STACK 1000h

.CODE
main:

top:
    mov ax, 1
    jmp bottom


ORG 1000h               ; A huge block between top and bottom

bottom:
    cmp ax, 0

    je top              ; Correct jump because of '.386'

    mov ax, 4C00h       ; Return 0
    int 21h

END main