12.Команды передачи управления: условные и безусловные. Вызов процедур и прерываний, возврат управления после процедуры или прерывания.

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

Команды JMP, CALL, RET, INT и IRET передают выполнение адресату в программном сегменте. Адресат может находиться как в том же программном сегменте (близкая передача), так и в другом программном сегменте (дальняя передача).

Команда перехода

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

Команды вызова процедур

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

Команды возврата и возврата-из-прерывания

RET (Возврат из процедуры) завершает выполнение процедуры и передает управление команде, следующей за командой CALL, которая вызвала данную процедуру.

Команда RET восстанавливает содержимое регистра EIP, которое было сохранено в стеке при вызове процедуры. Команда RET имеет необязательный операнд непосредственного значения. Когда операнд имеется, эта константа прибавляется к содержимому регистра ESP, что имеет эффект удаления всех параметров, сохраненных в стеке перед вызовом процедуры.

IRET (Возврат из прерывания) возвращает управление прерванной процедуре. Команда IRET отличается от команды RET тем, что она восстанавливает содержимое регистра EFLAGS из стека. Содержимое регистра EFLAGS запоминается в стеке при возникновении прерывания.

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

Команды условной передачи управления являются переходами, которые передают управление, если состояния регистра EFLAGS удовлетворяет условиям, заданным в команде.

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

В Таблице 3-3 приведена мнемоника команд перехода. Команды, приведенные парами, являются альтернативными именами одной и той же команды. Язык ассемблера поддерживает эти имена для большей ясности листингов программ. Разрешена форма команды условного перехода, которая использует смещение, суммируемое с содержимым регистра EIP, если указанное условие верно. Смещение может быть байтом или двойным словом. Смещение имеет знак; оно может быть использовано для перехода вперед и назад.

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

Команды управления циклом являются командами условного перехода, которые используют значение, помещенное в регистр ECX, в качестве счетчика числа выполнений тела цикла. все команды управления циклом уменьшают значение регистра ECX при каждом выполнении цикла и завершают работу при достижении значения ноль. Четыре из пяти команд управления циклом воспринимают флаг ZF в качестве условия завершения цикла до момента достижения счетчиком цикла значения ноль.

LOOP приводит к выполнению части программы, которое повторяется до тех пор, пока счетчик не станет равным нулю. Когда достигается значение нуля, выполнение передается команде, следующей непосредственно за командой LOOP. Если значение регистра ECX равняется нулю перед первым выполнением цикла, счетчик цикла умеьшается на 1, регистру присваивается значение 0FFFFFFFFH и цикл выполняется 2**32 раза.

LOOPE (Цикл до тех пор, пока равенство) и LOOPZ (Цикл до тех пор, пока ноль) являются синонимами одной и той же команды. Эти командыявляются командами условного перехода, которые уменьшают содержимое регистра ECX перед проверкой условия завершения цикла. Если значение регистра ECX не равно нулю и установлен флаг ZF, программа передает управление по адресу, указанному в качестве операнда назначения в команде. Когда достигнуто значение нуля или флаг ZF очищен, выполнение передается команде, следующей непосредственно за командой LOOPE/ LOOPZ.

LOOPNE (Цикл до тех пор, пока неравенство) и LOOPNZ (Цикл до тех пор, пока не ноль) являются синонимами одной и той же команды. Эти команды являются командами условного перехода, которые уменьшают содержимое регистра ECX перед проверкой условия завершения цикла. Если значение регистра ECX не равно нулю и очищен флаг ZF, программа передает управление по адресу, указанному в качестве операнда назначения в команде. Когда достигнуто значение нуля или флаг ZF установлен, выполнение передается команде, следующей непосредственно за командой LOOPNE /LOOPNZ.

Выполнение цикла или повтор ноль раз

JECXZ (Переход, если ECX равен нулю) переходит по адресу, указанному в команде в качестве операнда назначения, если в регистре ECX содержится значение ноль. Команда JECXZ используется совместно с командой LOOP и с командами сканирования строки и сравнения. Так как эти команды уменьшают значение регистра ECX перед проверкой на ноль, цикл будет выполняться 2**32 раза, если обращение к циклу произошло, когда в регистре ECX содержалось значение ноль. Команда JECXZ используется для создания циклов, которые пропускаются без выполнения, если начальное значение равно нулю. Команда JECXZ в начале цикла может быть использована для перехода за пределы цикла, если значение счетчика цикла равняется нулю. Когда команда используется вместе с повторяющимся командами сканирования строки и сравнения, JECXZ может определить условие окончания цикла до достижения счетчиком значения нуля или до выполнения условий сканирования или сравнения.

Программные прерывания

Команды INT, INTO и BOUND позволяют программисту осуществлять передачу управления программе обработки прерываний или исключениям.

INTn (Программное прерывание) вызывает программу обработки, указанную вектором прерываний, заданным в команде. Команда INT может задавать любые типы прерываний. Эта команда используется для поддержки множества типов программных прерываний или для проверки работы сервисных программ обработки прерываний. Сервисные программы обработки прерываний завершаются командой IRET, которая передает управление к команде, следующей за командой INT.

INTO (Прерывание по переполнению) вызывает программу обработки исключений по переполнению, если установлен флаг OF. Если данный флаг очищен, выполнение продолжается без вызова программы обработки. Флаг OF устанавливается арифметическими и логическими командами и командами работы со строками. Команда INTO поддерживает использование программных прерываний для обработки ошибочных ситуаций, таких, как арифметическое переполнение.

BOUND (Обнаружить выход значения за допустимые границы) сравнивает значение со знаком, хранящееся в регистре общего назначения, с верхним и нижним пределами. Программа обработки исключений по контролю выхода за допустимые границы вызывается, если значение, содержащееся в регистре, меньше чем нижняя граница, или больше чем верхняя граница. Эта команда поддерживает использование программных прерываний для контроля выхода за допустимые границы, таких как проверка индекса массива, чтобы убедиться в том, что он попадает в диапазон границ, заданный для массива. Команда BOUND имеет два операнда. Первый операнд указывает регистр общего назначения, который необходимо проверить. Второй операнд указывает базовый адрес двух слов или двух двойных слов, расположенных по соседству в памяти. Нижней границей является слово или двойное слово с младшим адресом, верхняя граница имеет старший адрес. Команда BOUND предполагает, что верхнее граничное значение и нижнее граничное значение расположены в смежных ячейках памяти. Верхняя и нижняя граница не могут быть операндами-регистрами; если же они таковыми являются, возникает исключение по неверному коду операции. Верхняя и нижняя границы массива могут располагаться в памяти даже до самого массива. Это позволяет задавать границы массива как постоянное смещение относительно начала массива. Так как адрес массива уже должен находиться в регистре, такая практика позволяет избежать дополнительных циклов шины для получения эффективной адресации границ массива.