Как формируется машинный код команды безусловного перехода ассемблера
Перейти к содержимому

Как формируется машинный код команды безусловного перехода ассемблера

  • автор:

Команда безусловного перехода

Безусловный переход в программе на Ассемблере производится по команде JMP. Полный формат команды следующий:

JMP[модификатор]адрес_перехода.

Адрес перехода может быть либо меткой, либо адресом области памяти, в которую предварительно помещен указатель перехода.

В системе команд микропроцессора существуют несколько кодов машинных команд безусловного перехода. Их различия определяются дальностью перехода и способом задания целевого адреса. Дальность перехода определяется местоположением операнда адрес_перехода. Этот адрес может находиться в текущем сегменте кода или в некотором другом сегменте. В первом случае переход называется внутрисегментным или близким, а во втором случае – межсегментным или дальним.

Внутрисегментный переход предполагает, что изменяется только содержимое регистра IP. Можно выделить три варианта внутрисегментного перехода:

  • прямой короткий;
  • прямой;
  • косвенный.

Как формируется машинный код команды безусловного перехода ассемблера

На этом шаге мы рассмотрим организацию безусловного перехода .

  • использование безусловного перехода;
  • организация цикла;
  • переходы по условию:
    • шаг 28: «Переходы для беззнаковых и знаковых данных»,
    • шаг 29: «Переходы для беззнаковых данных»,
    • шаг 30: «Переходы для знаковых данных»,
    • шаг 31: «Специальные арифметические проверки»;

    Команда JMP

    Эта команда предназначена для выполнения безусловного перехода. Ее общий вид следующий:

    • к значению регистра AX прибавляется 1;
    • к значению регистра AX прибавляется содержимое регистра BX ;
    • удваивается значение в регистре CX .

    Многократное повторение этих команд приводит к увеличению содержимого регистров AX — на 1; BX — на величину, находящуюся в регистре AX ; CX — в 2 раза. Повторяющиеся команды начинаются с метки A20 . Переход на эту метку осуществляется при выполнении команды JMP A20 . Так как здесь не предусмотрен выход из повторения, то программа будет выполняться бесконечно.

    TITLE EXJUMP Организация цикла с помощью JMP. CODESG SEGMENT PARA ASSUME: CS:CODESG,DS:CODESG,SS:CODESG ORG 100h Main PROC NEAR MOV AX,01 MOV BX,01 MOV CX,01 A20: ADD AX,01 ADD BX,CX SHL CX,1 JMP A20 Main ENDP CODESG ENDS END Main

    1. Директива ORG 100H устанавливает относительный адрес для начала выполнения программы. Ее использование необходимо, если создается COM -файл. В общем случае здесь приведен как раз пример COM -файла.
    2. Команда SHL осуществляет сдвиг влево содержимого первого операнда, а команда SHR осуществляет сдвиг вправо . Сдвиг на один бит кодируется в команде значением 1. Сдвиг более чем на один бит требует указания этого значения в регистре CL . Тогда следующая последовательность команд осуществляет сдвиг значения, находящегося в регистре BX на 2 бита влево:

    MOV CX, 2 SHL BX, CX .

    Команда JMP для перехода в пределах от -128 до +127 байт имеет тип SHORT . В этом случае генерируется однобайтовый код. Команда JMP , превосходящая эти пределы, получает тип NEAR (ее длина 2 байта) или FAR (3 байта). При необходимости генерировать команду JMP определенного типа, в ней используют перечисленные параметры, например:

    JMP SHORT A90 . . . A90: . . .

    На следующем шаге мы рассмотрим организацию цикла в языке программирования Ассемблер.

    Как формируется машинный код команды безусловного перехода ассемблера

    Безусловные переход — это такой переход, который передает управление всякий раз, когда он выполняется. Наоборот, условный переход проверяет текущее состояние машины, чтобы определить, передавать управление или нет. Существует два вида команд безусловной передачи управления — команды переходов и вызовов.

    Все команды вызова CALL — безусловны. Различные команды CALL показаны на рис.4.27. Близкий вызов CALL, или NEAR CALL, указывает новое значение регистра IP и сохраняет старое значение регистра IP в стеке в качестве адреса возврата. Далекий вызов CALL, или FAR CALL, задает новые значения сегмента и смещения для дальнейшего выполнения программы и сохраняет в стеке как регистр IP, так и регистр CS. Близкий непосредственный вызов CALL — это относительный переход, использующий двухбайтовое поле смещения. Все остальные команды вызова — абсолютные переходы. Непосредственный вызов FAR CALL требует четырехбайтовое поле операнда для указания новых значений для регистров CS и IP. Косвенные переходы используют байт адресации mod=r/m для указания операнда-регистра или памяти; этот операнд содержит адрес подпрограммы. Косвенные вызовы типа NEAR загружают однословный операнд в регистр IP. Вызовы типа FAR загружают двойное слово из памяти в пару регистров CS:IP; первое слово загружается в регистр IP, а второе — в регистр CS. Если команда указывает регистр в качестве операнда косвенного далекого вызова, результат непредсказуем; микропроцессор 8088 берет новое значение регистра CS неизвестно откуда. Ни в коем случае нельзя использовать эту модификацию команды.

    Командам CALL соответствуют команды возврата RET. Все возвраты — косвенные переходы, поскольку они извлекают адрес перехода из вершины стека. Близкий возврат извлекает из стека одно слово и помещает его в регистр IP, а далекий возврат извлекает два слова, помещая слово из меньшего адреса в регистр IP, а слово из большего адреса в регистр CS.

    Программы могут модифицировать возвраты как типа NEAR, так и типа FAR, указывая параметр счетчика байтов. Команда возврата прибавляет его значение к указателю стека после извлечения из него адреса (адресов) возврата. Такая команда позволяет программе удалять параметры из стека без использования специальных команд POP; тем самым подчеркивается, что стек — носитель передаваемых подпрограмме параметров. Такой стиль работы со стеком мы уже обсуждали во всех подробностях ранее в разделе «Работа со стеком».

    Команды безусловного перехода JMP идентичны командам CALL по их возможностям адресации. Однако существует дополнительная команда перехода, указывающая однобайтовое смещение для близкого относительного перехода (команда короткого перехода). Соответствующей ей команды CALL не существует, так как вызовы подпрограмм, расположенных поблизости, происходят очень редко. Команды переходов используют те же методы генерации адреса, что и команды вызова.

    Сделаем здесь замечание об оптимизации кода и о том, как работает ассемблер. По мере того, как ассемблер делает первый переход по тексту программы и назначает адреса командам, он должен решить, использовать двух- или трехбайтовую разновидность команды JMP. Если это переход назад, т.е. на место, уже известное ассемблеру, он может определить правильное смещение; тем самым ассемблер знает, находится ли переход в диапазоне короткого смещения. Однако, если переход делается вперед, на метку, о которой ассемблер еще не знает, он должен предположить, что метка находится далее, чем 128 байт от текущего места. Затем ассемблер порождает длинную форму команды перехода. Худший случай ассемблер обязан выбирать потому, что потом уже не может возвратиться назад и увеличить размер команды. Затем ассемблер заместит трехбайтовую команду перехода двухбайтовой командой JMP и однобайтовой командой NOP, если обнаружит, что переход делается ближе 128 байт от текущего места. Так как такой переход выполняется несколько быстрее, время выполнения в этом случае сокращается, но объектный код остается больше необходимого.

    Если программисту заранее известно, что переход вперед делается на место, лежащее в диапазоне 128 байт от текущего места, он может об этом сообщить ассемблеру с помощью следующей строки:

    JMP SHORT LABEL

    Атрибут SHORT заставляет ассемблер сформировать короткую форму SHORT команды перехода, даже если он еще не встречал метку. Если же программист сделал ошибку и переход в действительности не может быть коротким, ассемблер выдает сообщение об ошибке. На рис.4.26 дан пример оператора SHORT.

    Рисунок 4.28 показывает, как можно устроить таблицу переходов с помощью команды косвенного перехода. В этом примере делается выбор среди нескольких программ, основываясь на значении аргумента в регистре AL. Аналогичная программа могла бы вызвать подпрограмму по индексу. Это — реализация на языке ассемблера оператора CASE, который существует в некоторых языках высокого уровня.

    Как формируется машинный код команды безусловного перехода ассемблера

    Справочная система по языку Assembler

    https://vulkantm.com диссертация на тему кордиеритовая керамика. | http://www.putevka-perm.ru/ пермь предприятия города демидково санаторий.

    Команды передачи управления

    • безусловным — в данной точке необходимо передать управление не той команде, которая идет следующей, а другой, которая находится на некотором удалении от текущей команды;

    1. Команды безусловной передачи управления:
      • команда безусловного перехода;
      • вызова процедуры и возврата из процедуры;
      • вызова программных прерываний и возврата из программных прерываний.
    2. Команды условной передачи управления:
      • команды перехода по результату команды сравнения cmp ;
      • команды перехода по состоянию определенного флага;
      • команды перехода по содержимому регистра ecx/cx.
    3. Команды управления циклом:
      • команда организации цикла со счетчиком ecx/cx;
      • команда организации цикла со счетчиком ecx/cx с возможностью досрочного выхода из цикла по дополнительному условию.

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

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

    • near ptr — прямой переход на метку внутри текущего сегмента кода. Модифицируется только регистр eip/ip (в зависимости от заданного типа сегмента кода use16 или use32) на основе указанного в команде адреса (метки) или выражения, использующего символ извлечения значения СчА — $;
    • far ptr — прямой переход на метку в другом сегменте кода. Адрес перехода задается в виде непосредственного операнда или адреса (метки) и состоит из 16-битного селектора и 16/32-битного смещения, которые загружаются, соответственно, в регистры cs и ip/eip;
    • word ptr — косвенный переход на метку внутри текущего сегмента кода. Модифицируется (значением смещения из памяти по указанному в команде адресу, или из регистра) только eip/ip. Размер смещения 16 или 32 бит;
    • dword ptr — косвенный переход на метку в другом сегменте кода. Модифицируются (значением из памяти — и только из памяти, из регистра нельзя) оба регистра, cs и eip/ip. Первое слово/двойное слово этого адреса представляет смещение и загружается в ip/eip; второе/третье слово загружается в cs.

    Команда безусловного перехода jmp

    Синтаксис команды безусловного перехода
    jmp [модификатор] адрес_перехода — безусловный переход без сохранения информации о точке возврата.

    Адрес_перехода представляет собой адрес в виде метки либо адрес области памяти, в которой находится указатель перехода.

    • прямой короткий;
    • прямой;
    • косвенный.

    Процедуры

    • механизм процедур;
    • макроассемблер;
    • механизм прерываний.

    Для описания последовательности команд в виде процедуры в языке ассемблера используются две директивы: PROC и ENDP .

    Синтаксис описания процедуры таков (рис. 1).

    Рис. 1. Синтаксис описания процедуры в программе

    Из рис. 1 видно, что в заголовке процедуры (директиве PROC) обязательным является только задание имени процедуры. Среди большого количества операндов директивы PROC следует особо выделить [расстояние] .
    Этот атрибут может принимать значения near или far и характеризует возможность обращения к процедуре из другого сегмента кода. По умолчанию атрибут [расстояние] принимает значение near .

    Процедура может размещаться в любом месте программы, но так, чтобы на нее случайным образом не попало управление. Если процедуру просто вставить в общий поток команд, то микропроцессор будет воспринимать команды процедуры как часть этого потока и соответственно будет осуществлять выполнение команд процедуры.
    Более подробно вопросы, связанные с описанием и использованием процедур в программах ассемблера, рассматриваются на уроках 10 и 14. Примеры использования процедур вы можете посмотреть в приложении 7.

    Условные переходы

    • отношение между операндами со знаком (“больше — меньше”);
    • отношение между операндами без знака (“выше — ниже”)2;
    • состояния арифметических флагов zf, sf, cf, of, pf (но не af).

    Как видно, мнемокод всех команд начинается с “ j ” — от слова jump (прыжок), cc — определяет конкретное условие, анализируемое командой.
    Что касается операнда метка_перехода, то эта метка может находится только в пределах текущего сегмента кода, межсегментная передача управления в условных переходах не допускается . В связи с этим отпадает вопрос о модификаторе, который присутствовал в синтаксисе команд безусловного перехода. В ранних моделях микропроцессора (i8086, i80186 и i80286) команды условного перехода могли осуществлять только короткие переходы — на расстояние от –128 до +127 байт от команды, следующей за командой условного перехода. Начиная с модели микропроцессора 80386 это ограничение снято, но, как видите, только в пределах текущего сегмента кода.

    • любая команда, изменяющая состояние арифметических флагов;
    • команда сравнения cmp , сравнивающая значения двух операндов;
    • состояние регистра ecx/cx.

    Команда сравнения cmp

    Команда сравнения cmp имеет интересный принцип работы. Он абсолютно такой же, как и у команды вычитания.
    sub операнд_1,операнд_2 . Команда cmp так же, как и команда sub , выполняет вычитание операндов и устанавливает флаги. Единственное, чего она не делает — это запись результата вычитания на место первого операнда.

    Синтаксис команды cmp:
    cmp операнд_1,операнд_2 (compare) — сравнивает два операнда и по результатам сравнения устанавливает флаги.

    Флаги, устанавливаемые командой cmp , можно анализировать специальными командами условного перехода. Прежде чем мы их рассмотрим, уделим немного внимания мнемонике этих команд условного перехода (табл. 1). Понимание обозначений при формировании названия команд условного перехода (элемент в названии команды jcc , обозначенный нами cc ) облегчит их запоминание и дальнейшее практическое использование.

    Таблица 1. Значение аббревиатур в названии команды jcc

    Таблица 2. Перечень команд условного перехода для команды cmp операнд_1,операнд_2

    Не удивляйтесь тому обстоятельству, что одинаковым значениям флагов соответствует несколько разных мнемокодов команд условного перехода (они отделены друг от друга косой чертой в табл. 2).
    Разница в названии обусловлена желанием разработчиков микропроцессора облегчить использование команд условного перехода в сочетании с определенными группами команд. Поэтому разные названия отражают скорее различную функциональную направленность. Тем не менее, то, что эти команды реагируют на одни и те же флаги делает их абсолютно эквивалентными и равноправными в программе. Поэтому в табл. 2 они сгруппированы не по названиям, а по значениям флагов (условиям), на которые они реагируют.

    Команды условного перехода и флаги

    Мнемоническое обозначение некоторых команд условного перехода отражает название флага, с которым они работают, и имеет следующую структуру: первым идет символ “ j ” (jump, переход), вторым — либо обозначение флага, либо символ отрицания “ n ”, после которого стоит название флага.
    Такая структура команды отражает ее назначение.
    Если символа “n” нет, то проверяется состояние флага, и если он равен 1, производится переход на метку перехода.
    Если символ “n” присутствует, то проверяется состояние флага на равенство 0, и в случае успеха производится переход на метку перехода.
    Мнемокоды команд, названия флагов и условия переходов приведены в табл. 3.
    Эти команды можно использовать после любых команд, изменяющих указанные флаги.

    Таблица 3. Команды условного перехода и флаги

    Если внимательно посмотреть на табл. 2 и 3, видно, что многие команды условного перехода в них являются эквивалентными, так как в основе и тех, и других лежит анализ одинаковых флагов.

    Команды условного перехода и регистр ecx/cx

    Архитектура микропроцессора предполагает специфическое использование многих регистров.
    К примеру, регистр eax/ax/al используется как аккумулятор, а регистры bp, sp — для работы со стеком.
    Регистр ecx/cx тоже имеет определенное функциональное назначение — он выполняет роль счетчика в командах управления циклами и при работе с цепочками символов. Возможно, что функционально команду условного перехода, связанную с регистром ecx/cx , правильнее было бы отнести к этой группе команд.
    Синтаксис этой команды условного перехода таков:
    jcxz метка_перехода (Jump if cx is Zero) — переход, если cx ноль;
    jecxz метка_перехода (Jump Equal ecx Zero) — переход, если ecx ноль.

    Эти команды очень удобно использовать при организации цикла и при работе с цепочками символов.
    Нужно отметить ограничение, свойственное команде jcxz/jecxz . В отличие от других команд условной передачи управления, команда jcxz/jecxz может адресовать только короткие переходы — на –128 байт или на +127 байт от следующей за ней команды.

    Организация циклов

    Цикл, как известно, представляет собой важную алгоритмическую структуру, без использования которой не обходится, наверное, ни одна программа.
    Организовать циклическое выполнение некоторого участка программы можно, к примеру, используя команды условной передачи управления или команду безусловного перехода jmp. При такой организации цикла все операции по его организации выполняются “вручную”. Но, учитывая важность такого алгоритмического элемента, как цикл, разработчики микропроцессора ввели в систему команд группу из трех команд, облегчающую программирование циклов. Эти команды также используют регистр ecx/cx как счетчик цикла.
    Дадим краткую характеристику этим командам:

    • декремента регистра ecx/cx;
    • сравнения регистра ecx/cx с нулем:
      • если (ecx/cx) > 0, то управление передается на метку перехода;
      • если (ecx/cx) = 0, то управление передается на следующую после loop команду.

      • декремента регистра ecx/cx;
      • сравнения регистра ecx/cx с нулем;
      • анализа состояния флага нуля zf:
        • если (ecx/cx) > 0 и zf = 1, управление передается на метку перехода;
        • если (ecx/cx) = 0 или zf = 0, управление передается на следующую после loop команду.

        • декремента регистра ecx/cx;
        • сравнения регистра ecx/cx с нулем;
        • анализа состояния флага нуля zf:
          • если (ecx/cx) > 0 и zf = 0, управление передается на метку перехода;
          • если (ecx/cx)=0 или zf=1, управление передается на следующую после loop команду.

          Недостаток команд организации цикла loop, loope/loopz и loopne/loopnz в том, что они реализуют только короткие переходы (от –128 до +127 байт). Для работы с длинными циклами придется использовать команды условного перехода и команду jmp, поэтому постарайтесь освоить оба способа организации циклов.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *