Главная страница
Навигация по странице:

  • Безусловные переходы Основная команда, которая передает управление в другую точку программы - это JMP . Основной синтаксис команды JMP

  • Короткие условные переходы Подобно команде JMP

  • Команды перехода, проверяющие одиночный флаг

  • Команды перехода для чисел со знаками

  • Команды перехода для чисел без знаков

  • Emu8086 Запускаем программу Emu8086 и создаём новый файл через меню file new com template (Файл Новый Шаблон файла com). В редакторе исходного кода после этого мы увидим следующее Рис. Создание нового файла в Emu8086


    Скачать 251.21 Kb.
    НазваниеEmu8086 Запускаем программу Emu8086 и создаём новый файл через меню file new com template (Файл Новый Шаблон файла com). В редакторе исходного кода после этого мы увидим следующее Рис. Создание нового файла в Emu8086
    Дата05.04.2018
    Размер251.21 Kb.
    Формат файлаdocx
    Имя файлаEmu8086.docx
    ТипДокументы
    #40430
    страница7 из 10
    1   2   3   4   5   6   7   8   9   10

    Управление ходом программы


    Управление ходом программы - очень важная вещь. Это то, что заставляет программу принимать решения, в зависимости от некоторых условий. 


    • Безусловные переходы

      Основная команда, которая передает управление в другую точку программы - это JMP

      Основной синтаксис команды JMP:

    JMP метка

    Чтобы объявить метку в вашей программе, просто напечатайте ее имя и в конце добавьте двоеточие ":". Метка может быть любой комбинацией символов, но не должна начинаться с цифры. Например, ниже представлены три правильных объявления меток:

    label1:
    label2:
    a:

    Метка может быть объявлена на отдельной строке или перед любой другой командой, например:

    x1:
    MOV AX, 1

    x2: MOV AX, 2

    Здесь представлен пример команды JMP:


    ORG 100h
    MOV AX, 5 ; записать в AX число 5.

    MOV BX, 2 ; записать в ВX число 5.
    JMP calc ; перейти к 'calc'.
    back: JMP stop ; перейти к 'stop'.
    calc:

    ADD AX, BX ; прибавить BX к AX.

    JMP back ; перейти к 'back'.
    stop:
    RET ; вернуться в операционную систему.
    END ; директива для прекращения компиляции.


    Конечно, есть более простой путь для вычисления результата с двумя числами, но это хороший пример применения командыJMP
    Как вы можете видеть из этого примера, команда JMP может передавать управление другому участку программы, который может находиться как после этой команды, так и перед ней. Этот переход может быть осуществлен в пределах текущего сегмента кода (65,535 байтов). 


    • Короткие условные переходы

      Подобно команде JMP, которая выполняет безусловный переход, существуют команды, которые осуществляют условный переход (переход, который осуществляется только в том случае, если выполняется определенное условие). Эти команды разделяются на три группы. Первая группа только проверяет отдельный флаг, вторая - сравнивает числа со знаком, третья - сравнивает числа без знака. 

      Команды перехода, проверяющие одиночный флаг 

      Команда

      Описание

      Условие

      Обратная команда

      JZ , JE

      Переход, если "равно" ("нуль"). Т.е. если сравниваемые значения равны, то ZF = 1 и переход выполняется

       ZF = 1

      JNZ, JNE

      JC , JB, JNAE

      Переход, если есть перенос ("ниже", "не выше или равно").

       CF = 1

      JNC, JNB, JAE

      JS

      Переход по знаку.

       SF = 1

      JNS

      JO

      Переход по переполнению.

       OF = 1

      JNO

      JPE, JP

      Переход, если есть паритет или паритет четный.

       PF = 1

      JPO













      JNZ , JNE

      Переход по "не равно" или по "не нуль"

       ZF = 0

      JZ, JE

      JNC , JNB, JAE

      Переход, если нет переноса ("выше или равно" или "не ниже").

       CF = 0

      JC, JB, JNAE

      JNS

      Переход, если нет знака.

       SF = 0

      JS

      JNO

      Переход, если нет переполнения.

       OF = 0

      JO

      JPO, JNP

      Переход, если нет паритета или паритет нечетный.

       PF = 0

      JPE, JP



    • Как вы можете видеть, существуют команды, которые выполняют одинаковые действия. Это нормально. Они даже ассемблируются в одинаковый машинный код, поэтому будет неплохо, если вы запомните, что при компиляции команды JE, после дизассемблирования вы получите ее как: JZ.
      Различные имена используются для того, чтобы делать программы более легкими для понимания и кодирования. 


      Команды перехода для чисел со знаками 

      Команда

      Описание

      Условие

      Обратная команда

      JE , JZ

      Переход, если "равно" (=).
      переход, если "ноль".

      ZF = 1

      JNE, JNZ

      JNE , JNZ

      Переход, если "не равно" (<>).
      Переход, если "не ноль".

      ZF = 0

      JE, JZ

      JG , JNLE

      Переход, если "больше" (>).
      Переход, если "не меньше или равно"(not <=).

      ZF = 0
      and
      SF = OF

      JNG, JLE

      JL , JNGE

      Переход, если "меньше" (<).
      Переход, если "не больше или равно"(not >=).

      SF <> OF

      JNL, JGE

      JGE , JNL

      Переход, если "больше или равно" (>=).
      Переход, если "не меньше" (not <).

      SF = OF

      JNGE, JL

      JLE , JNG

      Переход, если "меньше или равно" (<=).
      Переход, если "не больше" (not >).

      ZF = 1
      or
      SF <> OF

      JNLE, JG



    • <> - этот знак означает "не равно". 


      Команды перехода для чисел без знаков 

      Команда

      Описание

      Условие

      Обратная команда

      JE , JZ

      Переход, если "равно" (=).
      Переход, если "ноль".

      ZF = 1

      JNE, JNZ

      JNE , JNZ

      Переход, если "не равно" (<>).
      Переход, если "не ноль".

      ZF = 0

      JE, JZ

      JA , JNBE

      Переход, если "выше" (>).
      Переход, если "не ниже или равно" (not <=).

      CF = 0
      and
      ZF = 0

      JNA, JBE

      JB , JNAE, JC

      Переход, если "ниже" (<).
      Переход, если "не выше или равно" (not >=).
      Переход по переносу.

      CF = 1

      JNB, JAE, JNC

      JAE , JNB, JNC

      Переход, если "выше или равно" (>=).
      Переход, если "не ниже" (not <).
      Переход, если "нет переноса".

      CF = 0

      JNAE, JB

      JBE , JNA

      Переход, если "ниже или равно" (<=).
      Переход, если "не выше" (not >).

      CF = 1
      or
      ZF = 1

      JNBE, JA



    • Обычно, если требуется сравнить два числовых значения, то используют команду CMP (она делает то же самое, что и команда SUB (вычитание), но не сохраняет результат, а влияет только на флаги.

      Логика очень простая, например:

      требуется сравнить числа 5 и 2,

      5 - 2 = 3

      результат - НЕ НОЛЬ (Флаг Нуля - Zero Flag (ZF) установлен в0). 

      Другой пример:

      требуется сравнить 7 и 7,

      7 - 7 = 0

      результат - НОЛЬ! (Флаг Нуля - Zero Flag (ZF) установлен в 1 и команды JZ или JE выполнят переход). 

      Ниже приведен пример команды CMP и условного перехода:


      include emu8086.inc
      ORG 100h
      MOV AL, 25 ; записать в AL число 25.

      MOV BL, 10 ; записать в BL число 10.
      CMP AL, BL ; сравнить AL с BL.
      JE equal ; если AL = BL (ZF = 1), то перейти к метке equal.
      PUTC 'N' ; иначе, если AL <> BL, то продолжить выполнение

      JMP stop ; программы - напечатать 'N' и перейти к метке stop.
      equal: ; если программа на этой метке,

      PUTC 'Y' ; то AL = BL, поэтому выводим на экран 'Y'.
      stop:
      RET ; сюда приходим в любом случае
      END



    • Попробуйте вышеописанный пример с различными числами в ALи BL, откройте флаги, щелкнув по кнопке [FLAGS]. Используйте [Single Step - пошаговый режим] и наблюдайте за происходящим. Не забывайте перекомпилировать и перезагружать вашу программу после кажого сделанного вами в ней изменения (используйте клавишу F5). 




    • Все условные переходы имеют одно серьезное ограничение - в отличие от команды JMP, они могут выполнять переход только на 127 байтов вперед или на 128 байтов назад (учтите, что большие команды ассемблируются в 3 и более байтов). 

      Мы можем легко преодолеть это ограничение, используя следующий метод:

      • Взять обратную команду из приведенной выше таблицы и выполнить переход к метке label_x

      • Использовать команду JMP для перехода к нужному участку программы. 

      • Определить метку label_x: только после команды JMP

    label_x: - может быть любым именем. 

    Пример:


    include emu8086.inc
    ORG 100h
    MOV AL, 25 ; записать в AL число 25.

    MOV BL, 10 ; записать в BL число 10.
    CMP AL, BL ; сравнить AL с BL.


    JNE not_equal ; переход, если AL <> BL (ZF = 0).

    JMP equal

    not_equal:

    ; представим, что здесь у нас

    ; размещается код, который ассмеблируется

    ; более чем в 127 байтов...

    PUTC 'N' ; если мы оказались здесь, то AL <> BL,

    JMP stop ; тогда печатаем 'N', и переходим к метке stop.
    equal: ; если мы оказались здесь,

    PUTC 'Y' ; то AL = BL, тогда печатаем 'Y'.
    stop:
    RET ; сюда приходим в любом случае.
    END

    Другой, реже используемый метод, представляет собой применение непосредственного значения (адреса) вместо метки. Если непосредственное значение начинается с символа '$', то выполняется относительный переход - переход относительно текущего адреса. Компилятор вычисляет команду, которая находится по заданному смещению, и выполняет переход непосредственно к ней. Например:



    ORG 100h
    ; безусловный переход вперед:

    ; пропускаем следующие два байта,

    JMP $2

    a DB 3 ; 1 байт.

    b DB 4 ; 1 байт.
    ; переход назад на 7 байтов, если BL <> 0:

    ; (Команда JMP занимает 2 байта)

    MOV BL,9

    DEC BL ; 2 байта.

    CMP BL, 0 ; 3 байта.

    JNE $-7
    RET
    END


    1   2   3   4   5   6   7   8   9   10


    написать администратору сайта