В процессоре 8080 имеется пять флагов, четыре из которых используются для реализации условных переходов. Набор команд 8080 содержит девять команд безусловных и условных переходов, зависящих от того, чему равны флаги нуля, переноса, четности и знака: 1 или 0.
Прежде чем продемонстрировать эти команды, хочу познакомить вас с двумя другими типами команд, имеющих отношение к переходу. Первая — CALL (вызов), она аналогична команде перехода, за исключением того, что перед загрузкой нового адреса в счетчик команд процессор сохраняет предыдущий адрес. Где он сохраняет этот адрес? Разумеется, в стеке!
Эта стратегия подразумевает, что команда вызова сохраняет информацию о том месте,
Команды CALL и RET — чрезвычайно важные функции любого процессора, позволяющие программисту реализовывать подпрограммы, которые являются часто используемыми фрагментами кода. (Под словом «
Обратимся к примеру. В процессе написания программы на языке ассемблера у вас возникает необходимость в перемножении двух байтов. Вы пишете код для выполнения этой операции, а затем продолжаете работу с программой. На каком-то этапе вам снова требуется перемножить два байта. Поскольку вы уже знаете, как это сделать, можно просто использовать те же команды снова и снова. Собираетесь ли вы во второй раз ввести эти команды в память? Надеюсь, что нет, поскольку это пустая трата времени и памяти. Вместо этого вам следует просто перейти к предыдущему фрагменту кода. Правда, в данном случае обычная команда перехода не сработает, поскольку она не позволяет вернуться к тому месту, с которого был совершен переход. Именно в этом случае пригодятся команды CALL и RET.
Набор команд, позволяющих перемножить два байта, идеально подходит на роль подпрограммы. Давайте рассмотрим одну из них. В главе 17 подлежащие перемножению байты и произведение хранились в определенных ячейках памяти. Приведенная далее подпрограмма 8080 умножает байт в регистре B на байт в регистре C и помещает 16-битное произведение в регистр HL.
Обратите внимание: первая строка подпрограммы начинается с метки Multiply. Эта метка соответствует адресу ячейки памяти, в которой расположена подпрограмма. Подпрограмма начинается с двух команд PUSH. Как правило, она пытается сохранить (а в дальнейшем восстановить) значения любых регистров, которые могут ей потребоваться.
Затем подпрограмма записывает значение 0 в регистры H и L. Для этого вместо команды SUB можно было бы использовать команду MVI (Move Immediate — переместить непосредственно), однако в этом случае потребовались бы четыре команды, а не две. После выполнения подпрограммы в паре регистров HL будет содержаться произведение.
После этого подпрограмма перемещает содержимое регистра B (множитель) в A и проверяет, не равно ли оно 0. Если оно равно 0, подпрограмма завершается, так как произведение — 0. Поскольку значения в регистрах H и L уже равны 0, подпрограмма может просто использовать команду JZ (Jump If Zero — перейти, если ноль), чтобы перейти к двум командам POP в конце программы.
В противном случае подпрограмма записывает в регистр B значение 0. Теперь в паре регистров BC содержится 16-битное множимое, а в аккумуляторе (А) — множитель. Команда DAD прибавляет значение BC (множимое) к значению HL (произведение). Значение множителя в A уменьшается на 1. Пока он не станет равен 0, выполнение команды JNZ (Jump If Not Zero — перейти, если не ноль) будет приводить к повторному сложению значения BC со значением HL. Этот небольшой цикл будет выполняться до тех пор, пока количество операций сложения BC и HL не станет равным множителю. (Более эффективную подпрограмму для умножения можно написать, используя команды сдвига из набора команд процессора 8080.)
Эту подпрограмму для перемножения чисел, например 25h и 12h, можно использовать в программе, добавив следующий фрагмент кода.
MVI B,25h
MVI C,12h
CALL Multiply
Команда CALL сохраняет в стеке значение счетчика команд, которое представляет адрес команды, следующей после CALL. Затем CALL вызывает переход к команде, на которую указывает метка Multiply. Это начало подпрограммы. После того как подпрограмма рассчитает произведение, она выполнит команду RET, в результате чего в счетчик команд будет возвращено значение из стека. Затем будет выполнена команда, следующая после CALL.
Набор команд процессора 8080 предусматривает условные команды