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

Все команды вызова 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,  который существует в некоторых языках высокого уровня.