Прыжок назад на 1000 строк

Я пытался сделать код, который, когда вы дойдете до самого конца, спросит вас, хотите ли вы попробовать еще раз. Если вы нажмете «y», то он вернётся на 1000 строк назад, прямо в начало программы.

Ну, очевидно, не получилось, так как я получил ошибку "относительный прыжок вне диапазона". Поэтому я делал прыжки каждые 50 строк, всего было 20 прыжков, например

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

Теперь, после этого, я запустил программу, и когда я нажал «y», TASM как бы завис. Он просто отображал последний экран с вводом «y» и мигающим _. Я больше не мог нажать на символ.


person xTan    schedule 17.09.2015    source источник
comment
Как вы описали, должно работать. Ошибка должна быть в другом месте. Вы имели в виду TASM 4.1 вместо TASM 1.4?   -  person rkhb    schedule 17.09.2015
comment
Типа замер? Вы забыли пропустить безусловные прыжки, чтобы пропустить обратные прыжки в лестнице лосося? Ваш код, вероятно, находится в бесконечном цикле между start: и s20: jmp start.   -  person Peter Cordes    schedule 17.09.2015
comment
Привет спасибо. нет, я поставил безусловные переходы. в любом случае, я удалил лососевую лестницу и просто оставил jmp start в самом конце, и теперь программа работает :)   -  person xTan    schedule 17.09.2015
comment
@xTan: Вы используете Tasm Installer 1.4 (из sourceforge)? Если это так, то это TASM 3.0/TD 3.1 внутри DOSBox (который также устанавливается)   -  person Michael Petch    schedule 17.09.2015


Ответы (1)


В x86 вам не нужна каскадная последовательность переходов, так как jmp может перепрыгнуть через весь сегмент. Просто условный переход, такой как jne, имеет ограниченный диапазон. Таким образом, вы можете изменить ошибочный условный переход на комбинацию безусловного ближнего перехода и условного короткого перехода:

Например, изменить

.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 может сделать это автоматически за вас. Поместите «ПРЫЖКИ» в начале (или там, где вам это нужно) файла:

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

В наборе инструкций 80386 (ISA) есть инструкция для почти условного перехода. Если ваш эмулятор поддерживает ISA 80386 (DOSBox поддерживает), вы можете указать TASM использовать его. Вставьте директиву .386:

.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
person rkhb    schedule 17.09.2015
comment
о блин!!! так что безусловный переход (jmp) на самом деле не имеет ограничения диапазона, как условные переходы? черт, и вот я сделал что-то около 50 прыжков!! facepalm в любом случае, спасибо, братан. ты спасатель жизни! :D... о да, и моя программа теперь работает :) - person xTan; 17.09.2015
comment
Это просто ограничение TASM? 74 cb — это код операции для je rel8 (короткий переход), но 0F 84 cd — это ближний переход: JE rel32 или JE rel16 (в зависимости от префиксов и текущего режима). В руководстве Intel говорится кое-что об исключениях в реальном режиме при переходе за пределы текущего сегмента кода (например, если используется 32-битный префикс размера адреса), поэтому эти кодировки почти прыжка не ограничены 32-битным / 64-битным режимом. Пока вам на самом деле не нужен дальний прыжок для смены сегментов, вам не нужна пара jcc / jmp, верно? - person Peter Cordes; 17.09.2015
comment
@PeterCordes: это ограничение 8086. Почти условный переход 0F 8x ... был введен в архитектуре 80386. - person rkhb; 17.09.2015
comment
@rkhb: хорошо, ОП не сказал, что он нацелился на такое старое оборудование ... Это нормально для этих 16-битных DOS или что-то еще, что это вопросы, которые просто предполагают, что все знают, в какой среде этот код будет работать? Похоже, что некоторые люди думают, что x86 asm автоматически подразумевает отказ от написания (внутренних циклов) обычных 64-битных программ, которые выполняют обычные системные вызовы в обычных ОС, таких как Unix или Windows. - person Peter Cordes; 17.09.2015
comment
@PeterCordes: TASM сегодня обычно используется в среде DOS для создания программ DOS, то есть 16-битного 8086. В TASM есть расширенные параметры, но я не знаю, какой DOS-эмулятор использует OP и какие процессоры и режимы поддерживаются. эмулятором. Если вас раздражает x86, то отредактируйте его (в моем посте и в теге) :-) - person rkhb; 17.09.2015
comment
@rkhb: это определенно x86. Невозможно замести под ковер долгую и грязную историю x86. :P Моя жалоба в том, что некоторые люди не указывают, каким образом они используют x86, и думают, что x86 asm означает 16-битную DOS, и опускают этот тег и информацию в своем вопросе. Спасибо за информацию, что TASM обычно означает 16-битную DOS. Я также добавил тег DOS. - person Peter Cordes; 17.09.2015
comment
У меня на полке стоит Turbo Assembler 1.0 (TASM) (был вместе с Turbo C 2.0). TASM версий от 1.0 до 3.0 мог создавать код 386, но сам ассемблер был 16-битным. TASM 4.0 и более поздние версии поставлялись с ассемблером, который работал как 32-битное приложение (tasm32). У Borland не было TASM 1.4, но, чтобы внести путаницу, существует установщик TASM 1.4 для Windows, который устанавливает минималистскую версию TASM 3.0. Этот установщик здесь . Установщик TASM 1.4 поставляется с образом DOSBox и несколько урезанной версией Turbo Debugger 3.1 и TASM 3.0. - person Michael Petch; 17.09.2015
comment
@MichaelPetch: Спасибо. Я не знал о существовании этого TASM 1.4. TASM, известный как TASM-5, объявляет себя Turbo Assembler Version 4.1 Copyright (c) 1988, 1996 Borland International. - person rkhb; 17.09.2015
comment
@rkhb: Это верно в отношении TASM 5.0 в отношении TASM.EXE (при запуске он отображается как 4.1), но я, кажется, припоминаю, если вы запускали TASM32.EXE (32-разрядная версия), он отображался как 5.0. Чего я действительно не знаю, так это того, действительно ли TASM.EXE сильно изменился или Borland выпустила его с неправильным баннером. Но определенно путаница. - person Michael Petch; 17.09.2015