Прямой переход

В данном случае в качестве ор указывается метка той команды, на которую надо передать управление:

JMP <метка>

Пример:

JMP L ;следующей будет выполняться команда с меткой L

...

L: MOV АХ, 0

Достаточно лишь пометить нужную команду и в команде перехода указать ее метку. Адрес же вместо метки подставит сам ассемблер.

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

В ПК имеются две машинные команды прямого перехода, в одной из которых относительный адрес перехода задается в виде байта (такая команда называется коротким переходом), а в другой - в виде слова (это команда длинного перехода). В каждой из этих команд операнд рассматривается как целое со знаком (от -128 до +127 или от -2 15 до 2 15-1), поэтому при сложении его с IP значение этого регистра может как увеличиться, так и уменьшиться, т. е. возможен и переход вперед, и переход назад.

Естественно, возникает вопрос: в чем выгода от того, что указывается не сам адрес перехода, а его расстояние от команды перехода? Это объясняется стремлением создателей ПК сэкономить память, занимаемую командами перехода. Если в команде указывать сам адрес перехода, то на него придется всегда отводить слово (2 байта). Но практика показывает, что в большинстве случаев переходы делаются на команды, расположенные недалеко от команд перехода, поэтому разность между адресами этих двух команд, как правило, небольшая, для нее достаточно и байта. Учитывая это, создатели ПК сделали так, чтобы именно эта разность и указывалась в командах перехода, чтобы большинство команд перехода можно было сделать на один байт короче.

Оператор SHORT

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

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

JMP L ;длинный переход(3 байта)

JMP SHORT L ;короткий переход (2 байта)

...

L: ...

Оператор SHORT можно ставить и перед меткой, описанной раньше, т. е. при переходе назад, однако в этом случае ассемблер проигнорирует этот оператор, поскольку он и так будет знать "расстояние" перехода.