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


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

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



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

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

Всего в системе команд микропроцессора есть несколько кодов машинных команд безусловного перехода jmp.
Их различия определяются дальностью перехода и способом задания целевого адреса.
Дальность перехода определяется местоположением операнда адрес_перехода. Этот адрес может находиться в текущем сегменте кода или в некотором другом сегменте. В первом случае переход называется внутрисегментным, или близким, во втором — межсегментным, или дальним.
Внутрисегментный переход предполагает, что изменяется только содержимое регистра eip/ip.
Можно выделить три варианта внутрисегментного использования команды jmp:

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

Процедуры

Процедуры

До сих пор мы рассматривали примеры программ, предназначенные для однократного выполнения. Но приступив к программированию достаточно серьезной задачи, вы столкнетесь с тем, что у вас, наверняка, появятся повторяющиеся участки кода. Они могут быть небольшими, а могут занимать и достаточно много места. В последнем случае эти фрагменты будут существенно затруднять чтение текста программы, снижать ее наглядность, усложнять отладку и служить неисчерпаемым источником ошибок. В языке ассемблера есть несколько средств, решающих проблему дублирования участков программного кода. К ним относятся:

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

В данном разделе нами будут рассмотрены основы механизма процедур.

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

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

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

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

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

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

Размещение процедуры в начале сегмента кода предполагает, что последовательность команд, ограниченная парой директив PROC и ENDP, будет размещена до метки, обозначающей первую команду, с которой начинается выполнение программы. Эта метка должна быть указана как параметр директивы END обозначающей конец программы:

model small.stack 100h.data.code my_proc proc near... ret my_proc endp start:... endstart

Объявление имени процедуры в программе равнозначно объявлению метки, поэтому директиву PROC в частном случае можно рассматривать как завуалированную форму определения метки в программе. Поэтому сама исполняемая программа также может быть оформлена в виде процедуры, что довольно часто и делается с целью пометить первую команду программы, с которой должно начаться выполнение. При этом не забывайте, что имя этой процедуры нужно обязательно указывать в заключительной директиве END. Такой синтаксис мы уже неоднократно использовали в своих программах. Так, последний рассмотренный фрагмент будет абсолютно эквивалентен следующему:

 

model smalI.stack 100h.data.code my_proc proc near... ret my_proc endp start proc... start endp endstart

В этом фрагменте после загрузки программы в память управление будет передано первой команде процедуры с именем main.

Размещение процедуры в конце программы предполагает, что последовательность команд, ограниченная директивами PROC и ENDP, будет размещена после команды, возвращающей управление операционной системе.

model smalI.stack 100h.data.code start: mov ax,4c00h int 21h;возврат управления операционной системе myproc proc near... ret my_proc endp endstart

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

 

model small.stack 100h.data.code start:... jmp ml my_proc proc near... ret my_proc endp ml:... mov ax,4c00h int 21h;возврат управления операционной системе endstart

Последний вариант расположения описаний процедур — в отдельном сегменте кода — предполагает, что часто используемые процедуры выносятся в отдельный файл. Файл с процедурами должен быть оформлен как обычный исходный файл и подвергнут трансляции для получения объектного кода. Впоследствии этот объектный файл утилитой TLINK можно объединить с файлом, где процедуры используются. Использование утилиты TLINK описано в разделе Информация по использованию пакета TASM. Этот способ предполагает наличие в исходном тексте программы еще некоторых элементов, связанных с особенностями реализации концепции модульного программирования в языке ассемблера.

Как обратиться к процедуре? Так как имя процедуры обладает теми же атрибутами, что и обычная метка в команде перехода, то обратиться к процедуре, в принципе, можно с помощью любой команды перехода. Но есть одно важное свойство, которое можно использовать благодаря специальному механизму вызова процедур. Суть состоит в возможности сохранения информации о контексте программы в точке вызова процедуры. Под контекстом понимается информация о состоянии программы в точке вызова процедуры. В системе команд микропроцессора есть две команды, осуществляющие работу с контекстом. Это команды call и ret:

call [ модификатор ] имя_процедуры — вызов процедуры (подпрограммы). Команда call, подобно jmp, передает управление по адресу с символическим именем имя_процедуры, но при этом в стеке сохраняется адрес возврата. Адрес возврата — это адрес команды, следующей после команды call.
ret [ число ] — возвратить управление вызывающей программе. Команда ret считывает адрес возврата из стека и загружает его в регистры cs и ip/eip, тем самым возвращая управление на команду, следующую в программе за командой call. [ число ] — необязательный параметр, обозначающий количество элементов, удаляемых из стека при возврате из процедуры. Размер элемента определяется хорошо знакомыми нам параметрами директивы segment — usel6 или use32 (или соответствующим параметром упрощенных директив сегментации). Если указано use16, то [ число ] — это значение в байтах; если use32 — в словах.

Для команды call, как и для jmp, актуальна проблема организации ближних и дальних переходов. Это видно из формата команды, где присутствует [модификатор]. Как и в случае команды jmp, вызов процедуры командой call может быть:

  • внутрисегментным — процедура находится в текущем сегменте кода (имеет тип near), и в качестве адреса возврата команда call сохраняет только содержимое регистра ip/eip, что вполне достаточно для осуществления возврата (рис. 10.4);


Рис. 10.4. Содержимое стека до и после команды вызова процедуры ближнего типа

  • межсегментным — процедура находится в другом сегменте кода (имеет тип far), и для осуществления возврата команда call должна запомнить содержимое обоих регистров, cs и ip/eip. Очередность размещения их в стеке такова: сначала cs, затем ip/eip (рис. 10.5).

Важно отметить, что одна и та же процедура не может быть процедурой и ближнего, и дальнего типов. Таким образом, если процедура используется в текущем сегменте кода, но может вызываться и из другого сегмента программы, то она должна быть объявлена процедурой типа far. Подобно команде jmp, существуют четыре разновидности команды call. Какая именно команда будет сформирована, зависит от значения [ модификатор ] в команде вызова процедуры call и атрибута дальности в описании процедуры. Если процедура описана в начале сегмента данных с указанием дальности в ее заголовке, то при ее вызове [ модификатор ] можно не указывать: транслятор сам разберется, какую команду call ему нужно формировать. Если же процедура описана после ее вызова, например, в конце текущего сегмента или в другом сегменте, то при ее вызове нужно указать ассемблеру тип вызова, чтобы он мог за один проход правильно сформировать команду call. Значения [ модификатор ] такие же, как и у команды jmp, за исключением short ptr.

Рис. 10.5. Содержимое стека до и после команды вызова процедуры дальнего типа

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

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


Микропроцессор имеет 18 команд условного перехода (см. “Описание команд”). Эти команды позволяют проверить:

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

Команды условного перехода имеют одинаковый синтаксис:
jcc метка_перехода

Как видно, мнемокод всех команд начинается с “ 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

Мнемоническое обозначение Английский Русский Тип операндов
E e equal Равно Любые
N n not Не Любые
G g greater Больше Числа со знаком
L l less Меньше Числа со знаком
A a above Выше, в смысле “больше” Числа без знака
B b below Ниже, в смысле “меньше” Числа без знака

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

Типы операндов Мнемокод команды условного перехода Критерий условного перехода Значения флагов для осществления перехода
Любые je операнд_1 = операнд_2 zf = 1
Любые jne операнд_1<>операнд_2 zf = 0
Со знаком jl/jnge операнд_1 < операнд_2 sf <> of
Со знаком jle/jng операнд_1 <= операнд_2 sf <> of or zf = 1
Со знаком jg/jnle операнд_1 > операнд_2 sf = of and zf = 0
Со знаком jge/jnl операнд_1 => операнд_2 sf = of
Без знака jb/jnae операнд_1 < операнд_2 cf = 1
Без знака jbe/jna операнд_1 <= операнд_2 cf = 1 or zf=1
Без знака ja/jnbe операнд_1 > операнд_2 cf = 0 and zf = 0
Без знака jae/jnb операнд_1 => операнд_2 cf = 0

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



Поделиться:


Последнее изменение этой страницы: 2017-02-05; просмотров: 558; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 44.192.132.66 (0.108 с.)