С. Ахманов, А. Нечаев, А. Скурихин

Архитектура процессора КР580ВМ80А

Мы попытаемся рассказать, что такое процессор КР580ВМ80А, используемый в ПЭВМ "Корвет", с точки зрения программиста, и надеемся, что, прочитав статью, вы сможете начать писать программы на ассемблере.

Прежде чем перейти к описанию процессора, поговорим немного о том, что такое компьютер, из чего он состоит, какое место в нем занимает процессор.

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

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

Примерно так функционирует свободное общество людей; примерно так работают некоторые из так называемых нейрокомпьютеров.

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

Такую систему не интересуют цели отдельных компонентов (людей). Единственное, что безусловно требуется, - исполнение распоряжений. Компонент, не выполняющий распоряжений, считается неисправным и устраняется.

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

Компьютер - система с централизованным управлением. Это обусловлено как тем, что отдельные компоненты компьютера не имеют собственных целей, так и тем, что цель компьютеру задается извне - он должен делать то, что хотите вы.

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

К счастью, программисту обычно не удается замаскировать свою деятельность: всегда можно быстро сравнить "продукцию" компьютера с поставленными целями и, если результат сравнения вас не устраивает, отказаться от услуг данного программиста. С аппаратом это сделать гораздо сложнее - не вы, а аппарат может отказаться от ваших услуг, если он вас не устраивает.

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

С программой работает уже сам компьютер.

Он состоит из трех подсистем - процессора, памяти и устройств ввода-вывода (УВВ). Подсистема УВВ связывает компьютер с внешним миром. Без нее компьютер не может ничего увидеть, ничего услышать, ничего сказать. В ее состав обычно входят клавиатура, дисплей, принтер, дисковод, мышь и т. д. Чтобы передать компьютеру программу, необходимо воспользоваться подсистемой УВВ.

Хранится программа в оперативной памяти (ОЗУ). Казалось бы, ОЗУ не является обязательным компонентом компьютера: можно не передавать компьютеру весь пакет распоряжений сразу, а давать по одному - пусть сначала выполнит одну команду, потом следующую и т. д. Так сделать действительно можно. Однако отдельные команды выполняются очень быстро, а подсистема ввода-вывода работает очень медленно (в сотни и тысячи раз медленнее). Поэтому отсутствие ОЗУ лишит компьютер его основного достоинства - способности очень быстро делать различные операции.

Кроме программного счетчика имеется еще один 16-разрядный регистр, предназначенный для хранения адреса - SP (от Stack Pointer - указатель стека). Стек - это особый способ хранения данных, устроенный по образу и подобию пистолетной обоймы (думается, что стараниями военруков даже девочки в нашей стране хорошо представляют себе, что это такое). Отличие только в том, что патроны утапливаются в обойму, а данные "кладутся" на стек сверху, после чего его "стенки" "подрастают". На "верхнее" (всегда на очередное "верхнее"!) данное и указывает содержимое SP. Такой механизм хранения данных (LIFO - last in first out, последним вошел - первым вышел) удобен для реализации некоторых алгоритмов, в частности при использовании подпрограмм.

Регистры А, В, С, D, Е, Н, L - 8-разрядные, предназначены в основном для хранения и обработки данных. Самый важный из них - А (его называют аккумулятором). С его участием выполняются практически все операции над данными (сложение, вычитание, сдвиг, логические операции и т. д.). Результат операции остается в аккумуляторе. Если какая-либо операция предполагает два операнда, то в качестве второго обычно используется содержимое одного из семи описываемых регистров.

С содержимым регистров В, С, D, Е, Н, L можно выполнять только две арифметические операции - увеличение и уменьшение содержимого на единицу. Зато эти регистры могут объединяться в пары, образуя три 16-разрядных регистра: ВС, DE и HL. Эти "двойные" регистры имеют свои специализации. Основная их функция - косвенная адресация (так называют использование ячейки, адрес которой не задан в команде явно, а записан в заданном в команде регистре). Команды с косвенной адресацией, использующие ВС и DE, позволяют производить только обмен данными между аккумулятором и памятью; HL в качестве адресного регистра используют значительно более разнообразные команды.

С 16-разрядными регистрами ВС, DE, HL и SP возможны и некоторые арифметические операции: увеличение и уменьшение содержимого на 1, а также сложение. Операция сложения требует двух операндов. Один из них всегда регистр HL, ero иногда называют 16-разрядным аккумулятором. Другой - один из ВС, DE, SP или снова HL.

Особняком стоит регистр флагов (его еще называют регистром состояния). Он "скрыт" от программиста - нельзя что-то записать в него так-же просто, как это можно сделать с другими регистрами.

Хотя современные компьютеры имеют довольно большой объем памяти, бывают случаи, когда вся программа не может поместиться в ОЗУ целиком. В этом случае ее дробят на отдельные части (их называют оверлейными модулями), которые по мере необходимости "подгружаются" в память из УВВ.

Процессор выполняет распоряжения и управляет всеми остальными подсистемами. Чтобы вполне понять, как это происходит, необходимо ознакомиться хотя бы с основными операторами языка ассемблера и элементами архитектуры процессора; в общих же чертах процедуру выполнения команд можно описать так.

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

А теперь мы можем перейти к описанию функций процессора и их использования.

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

Хотя разные процессоры обычно имеют отличные системы команд, существуют процессоры, система команд которых совместима с системой команд менее совершенных процессоров. Обычно разработчики обеспечивают это, чтобы обладатели их изделия могли воспользоваться наработанным ранее программным обеспечением. "Старший брат" нашего процессора - Z80 фирмы Zilog; целый ряд совместимых сверху вниз процессоров (т. е. таких, что более совершенные процессоры могут выполнить все команды менее совершенных) выпускает фирма Intel - i8088, i8086, i80286, i80386, i80486.

Но даже если процессоры несовместимы, в их системах команд обязательно присутствуют следующие четыре группы:

Процессор имеет довольно сложную внутреннюю структуру. С точки зрения программиста он состоит из нескольких ячеек памяти, называемых регистрами процессора, и триггеров, состоянием которых можно управлять из программы. Ячейки памяти процессора (далее мы будем называть их регистрами процессора) отличаются от ячеек основной памяти тем, что они не пронумерованы. Вместо номера каждой ячейке присвоено собственное имя - идентификатор. Это подчеркивает, что регистры процессора не равнозначны между собой, более того, они могут иметь разную разрядность (размер). Некоторые из них используются только для хранения и обработки данных, другие используются только для хранения адреса, третьи могут использоваться и как адресные, и для данных.

Большинство действий процессора так или иначе связаны с перемещением или изменением содержимого регистров (они изображены на рис. 1).

Регистры
Рисунок 1. Регистры

С одним регистром мы уже познакомились под именем указателя команды - это PC (от Program Counter - программный счетчик). Он является 16-разрядным, хранит адрес ячейки, содержащей следующую команду, которую процессор должен выполнить. Когда процессор извлекает из памяти очередное распоряжение, содержимое PC автоматически увеличивается на 1; таким образом процессор готовится извлечь из памяти следующую команду. При подаче на процессор сигнала СБРОС (его нельзя подать с помощью программы, обычно для этого служит специальная кнопка) или при включении питания содержимое PC всегда устанавливается в 0, что обеспечивает определенность состояния процессора при первоначальном запуске (включении питания).

Некоторые команды могут "напрямую" изменять содержимое PC, что бывает необходимо при выполнении условных и безусловных переходов. Позднее мы их внимательно изучим. Все они относятся к группе команд управления работой программы.

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

Регистр флагов
Рисунок 2. Регистр флагов

Прочитать "в лоб" регистр флагов также нельзя - о состоянии его битов можно узнать только косвенно, по результатам работы команд условных переходов (о них мы расскажем чуть позже).

Регистр флагов при операциях со стеком образует с аккумулятором 16-разрядное слово, причем содержимое аккумулятора становится старшим, а регистр флагов - младшим байтом этого слова. Эта пара обозначается PSW (Processor State Word - слово состояния процессора). Благодаря этому записать и считать регистр флагов в явном виде все-таки можно, используя стек (подробнее об этом будет рассказано позже).

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

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

Источником прерывания послужил звонок телефона. Благодаря этому устройству вы сразу узнаете, что кто-то хочет связаться с вами. Представьте, что звонка нет (или он неисправен). Тогда, чтобы узнать, "звонит" кто-нибудь или нет, придется каждую минуту поднимать телефонную трубку и слушать. Человек на такое вряд ли согласится, а вот компьютеру приходится. Несмотря на кажущуюся абсурдность, этот способ ожидания событий (он называется опросом, по-английски polling) используется довольно часто для организации общения процессора со сравнительно медленно работающими периферийными устройствами, например клавиатурой и принтером.

Недостатки опроса очевидны. Из-за малого КПД (сотни проверок "на всякий случай"!) он отнимает значительное время у основной программы, хуже того - усложняет алгоритм ее работы. Ведь чтобы не пропустить нужное событие, мы должны "натыкать" блоки опроса в разные части программы.

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

Расскажем о прерываниях подробнее. Предположим, что дополнительно к исполнению основной программы (пусть это будет война с космическими негодяями) компьютер должен отображать в углу экрана текущее время. Эти две задачи (игра и отображение времени) не связаны между собой. Игра - непрерывный процесс; реализующая ее программа должна перемещать какие-то объекты по экрану, реагировать на клавиши и т. д. Программа, имитирующая часы, должна следить за временем и каждую минуту обновлять показания на экране. Ясно, что ей не обязательно работать постоянно. Достаточно, если она будет включаться каждую секунду для увеличения счетчика и, если настала пора, вывода новых цифр на экран.

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

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

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

Описание конструкции процессора почти окончено, осталось упомянуть о способах общения с УВВ. В "Корвете" этим устройствам отводится часть ОЗУ, через которую процессор и обменивается данными с внешним миром; можно действовать и иначе - КР580ВМ80 имеет специальное адресное пространство ввода-вывода (отделенное от обычного 64-килобайтного) размером в 256 байтов. Ячейки этого пространства называются портами - видимо, чтобы подчеркнуть их роль "ворот" для связи, а также чтобы не путать с ячейками обычной памяти.

Команды КР580ВМ80

Разобравшись со структурой процессора, перейдем к описанию команд. В памяти они записываются, естественно, двоичными числами, но программисты практически всегда обозначают их буквенными аббревиатурами, так называемыми мнемониками. Мнемоники достаточно просто перевести в двоичные коды: "в жизни" переводом занимается транслятор-ассемблер, но можно произвести эту операцию и вручную. Мы будем приводить двоичные коды команд: знание лишним не бывает.

Что-то, возможно, будет вам непонятно; не переживайте. После основных сведений о командах пойдет рассказ об их использовании, и в нем по мере надобности будут разъясняться запутанные вещи. Впрочем, не обязательно дожидаться разъяснений: воспользуйтесь отладчиком (DDT или SID; входят в пакеты СР/М и ассемблера) - это прекрасный инструмент, позволяющий воочию и во всех тонкостях наблюдать процесс исполнения команд.

Начинающим осваивать ассемблер очень мешает отсутствие привычных чисел с плавающей запятой, символьных переменных и т. п. Тут уж ничего не поделаешь - процессор оперирует только с байтами и вариантов интерпретации их содержимого очень мало: целое число без знака (от О до 255) или со знаком (от -128 до 127). Впрочем, данные в виде пары байтов тоже иногда допустимы, но содержать они могут только целые числа без знака (от 0 до 65535). Все остальные виды данных приходится моделировать программисту.

Далее мы будем использовать следующие обозначения:

Команд пересылки данных довольно много, они позволяют производить обмен данными между 8- и 16-разрядным и регистрами и ячейками памяти.

Ячейки памяти состоят из 8 битов, но благодаря специальным соглашениям в них можно хранить не только 8-разрядные числа. Если, например, нужно записать в ОЗУ двухбайтовое (16-разрядное) число, его заносят в две последовательно расположенные ячейки, причем младший байт числа (разряды 0-7) помещается в ячейку с меньшим адресом (некоторые типы процессоров имеют обратный порядок размещения байтов числа).

Командам пересылки данных все равно, что пересылать, для них важна только длина числа. В зависимости от типа команды перемещаются байт или два байта.

Для пересылки байта пользуются командами однобайтовых пересылок. Они могут занести константу в любой 8-разрядный (байтовый) регистр (непосредственная загрузка); скопировать содержимое любого байтового регистра в любой другой; переписать содержимое аккумулятора в память и загрузить аккумулятор из памяти, причем адрес в памяти может быть указан в команде числом (прямая адресация) или задаваться именем одной из регистровых пар ВС, DE или HL (косвенная адресация; в регистровой паре должен быть записан нужный адрес). Наконец, возможны непосредственный обмен данными между любым регистром и памятью и непосредственная загрузка константы в память (при этом адрес в памяти должен задаваться содержимым HL). Есть еще две команды ввода-вывода, которые тоже можно отнести к этой группе; одна записывает содержимое аккумулятора в порт (портами называют ячейки из адресного пространства ввода-вывода, чтобы подчеркнуть их отличие от ячеек памяти), другая загружает аккумулятор из порта. Номер порта (от 0 до 255) указывается непосредственно в команде.

Таблица 1. Байтовые команды пересылки данных
N
п/п
Мнемоника Длительность
выполнения
(тактов)
Код Действие
1 MVI R,N 7 0 0 R R R 1 1 0
N N N N N N N N
Загрузка 8-разрядного числа в байтовый регистр
2 MVI M,N 10 0 0 1 1 0 1 1 0
N N N N N N N N
Загрузка 8-разрядного числа в ячейку памяти, адрес которой записан в HL
3 MOV R1,R2 5 0 1 R1 R1 R1 R2 R2 R2 Пересылка байта из регистра в регистр
4 MOV M,R 7 0 1 1 1 0 R R R Пересылка содержимого байтового регистра в ячейку памяти, адресуемую через HL
5 MOV R,M 7 0 1 R R R 1 1 0 Пересылка содержимого ячейки памяти, адресуемой через HL в байтовый регистр
6.1 STAX B 7 0 0 0 0 0 0 1 0 Пересылка содержимого аккумулятора в ячейку памяти, адресуемую через BC
6.2 STAX D 7 0 0 0 1 0 0 1 0 Пересылка содержимого аккумулятора в ячейку памяти, адресуемую через DE
7.1 LDAX B 7 0 0 0 0 1 0 1 0 Пересылка содержимого ячейки памяти, адресуемой через BC в аккумулятор
7.2 LDAX D 7 0 0 0 1 1 0 1 0 Пересылка содержимого ячейки памяти, адресуемой через DE в аккумулятор
8 LDA NN 13 0 0 1 1 1 0 1 0
N N N N N N N
N N N N N N N
Загрузка в аккумулятор содержимого ячейки памяти с адресом NN
9 STA NN 13 0 0 1 1 0 0 1 0
N N N N N N N
N N N N N N N
Загрузка в ячейку памяти с адресом NN содержимого из аккумулятора
10 IN N 10 1 1 0 1 1 0 1 1
N N N N N N N
Загрузка содержимого порта N в аккумулятор
11 OUT N 10 1 1 0 1 0 0 1 1
N N N N N N N
Загрузка содержимого из аккумулятора в порт N

Все байтовые команды пересылки данных приведены в таблице 1.

1. Загрузка 8-разрядного числа в байтовый регистр. Мнемоника команды имеет вид

    MVI R,N

и происходит от слов move immediate (непосредственная загрузка) (впрочем, уверенности, что именно эти слова имели в виду специалисты фирмы Intel, разработавшие мнемоники, нет; но мы все же будем приводить "расшифровки" - они очень облегчают запоминание).

Отметим кстати, что мнемоника команд процессора КР580ВМ80А выглядит не совсем удачной, в частности сильно различается для сходных по смыслу команд но тут ничего не поделаешь. В мнемониках команд более современных процессоров типа 8086, Z80 этого недостатка уже нет, а нам придется напрячь свою память.

При ее выполнении байт N записывается в байтовый регистр.

Рассмотрим машинное представление этой команды, т. е. ее код, В нем должны содержаться идентификация самой команды и используемого регистра, а также загружаемый байт N. Все это умещается в два байта (выпишем их побитно):

    0 0 R R R 1 1 0
N N N N N N N N

Первый кодирует команду (биты 7, 6, 2, 1, 0) и регистр (биты 5, 4, 3), во втором записано число N. Регистры здесь и далее кодируются следующим образом:

Таким образом, код, например, команды MVI А,1 имеет вид

    00111110
00000001

или в 16-ричном виде ЗЕ 01 (далее мы будем, как это принято, прибавлять к записи двоичных чисел В, а 16-ричных - Н: 00111110В, ЗЕН).

Эта команда выполняется за 7 тактов процессора. Если в нашей машине один такт требует 0,4 мкс, то вся команда выполнится за 7*0,4=2,8 мс.

Продолжительность выполнения команды зависит от числа производимых обращений к памяти (их еще называют машинными циклами). Первое обращение длится 4 такта, последующие - по 3. В данном случае для выполнения команды нужно считать только два байта ее кода, что и требует 4+3=7 тактов.

2. Загрузка 8-разрядного числа в ячейку памяти, адрес которой записан в регистровой паре HL. Мнемоника команды:

    MVI M,N

Поскольку предполагается, что адрес М находится в HL, не пытайтесь найти его в коде команды. Получив в качестве команды последовательность 00110110В, процессор использует число из HL как адрес ячейки памяти и записывает в нее второй байт кода команды.

Если, например, в HL содержалось число 3456Н, то при выполнении команды

    00110110В=36Н
10000000В=80Н

(т. е. MVI Мб80Н) содержимое ячейки с адресом 3456Н станет равным 80Н.

Отметим, что "ячейка" М во многих командах, не только в MVI, может использоваться аналогично байтовым регистрам. Она даже кодируется очень похоже; в приведенном выше столбце обозначений регистров после регистра L с кодом 101 можно было бы добавить М с кодом 110 (сравните коды команд MVI M,N и MVI R,N).

3. Пересылка байта из регистра в регистр. Мнемоника команды:

    MOV R1,R2

При ее выполнении (R2) (напоминаем, что скобками мы обозначаем содержимое, в данном случае содержимое регистра R2) пересылается в регистр R1. При этом само (R2) не изменяется.

Биты 7 и 6 ее кода задают тип команды, а биты 5, 4, 3 и 2, 1, 0 - названия регистров R1 и R2 (таким же образом, как и в команде MVI R,N). К примеру, код команды MOV A,L равен 01111101B=7DH.

4. Пересылка содержимого байтового регистра в ячейку памяти, адресуемую через HL. Мнемоника этой команды имеет вид

    MOV M,R

Для примера рассмотрим команду MOV М,В (код 01110000B=70Н К Если в HL хранится число 1234Н, а в регистре В - 71Н, то после ее выполнения в ячейке памяти с адресом 1234Н будет записано число 71Н; содержимое регистров В, Н, L не изменится.

5. Пересылка содержимого ячейки памяти, адресуемой при помощи HL, в байтовый регистр. Мнемоника и код этой команды:

    MOV R,M

Для примера рассмотрим команду MOV С,М (код 01001110В=4ЕН). Если в HL содержится число 5678Н, а в ячейке памяти с адресом 5678Н записано 55Н, то после ее выполнения в регистре С окажется число 55Н; (HL) и (5678Н) не изменяются.

При однобайтных пересылках ячейки памяти можно адресовать и через регистровые пары ВС и DE, но только в том случае, когда данные пересылаются в аккумулятор или из него.

6. Пересылка (А) в ячейку памяти, адресуемую через регистровую пару ВС или DE. Мнемоника команд:

    STAX B
STAX D

(от store accumulator - сохранить значение аккумулятора: буква X присутствует в мнемониках команд, оперирующих с регистровыми парами).

Пусть (ВС)=3210Н, (DE)=789AH, (A)=53Н. После выполнения команд

    STAX B
STAX D

ячейки памяти с адресами 3210Н и 789АН будут содержать число 53Н, содержимое регистров А, В, С, D и Е не изменится.

7. Пересылка содержимого ячеек памяти, адресуемых через регистровые пары ВС и DE, в аккумулятор. Мнемоника команд:

    LDAX B
LDAX D

Пусть (ВС)=5432Н, (DE)=4321H, (5432Н)=51Н, (4321Н)=72Н. Тогда после выполнения команды LDAX В содержимое ячейки памяти с адресом 5432Н будет помещено в аккумулятор, т. е. (А) станет равно 51Н. Если теперь выполнить команду LDAX D, (А) станет равно 72Н: (ВС), (DE), (5432Н), (4321Н) не изменяются.

8. Загрузка из ячейки памяти с адресом NN в аккумулятор. Мнемоника команды:

    LDA NN

Если, например, (9АВСН)=21Н, то после выполнения команды LDA 9АВСН, имеющей код

    00111010В=ЗАН
10111100B=ВСН
10011010B=9АН

в регистре А будет записано 21Н.

9. Загрузка содержимого аккумулятора в ячейку памяти. Мнемоника команды:

    STA NN

При выполнении, например, команды STА 7FECH, код которой имеет вид

    00110010В=32Н
    111011008=ЕСН
    01111111B=7FH

(А) будет помещено в ячейку памяти с адресом 7FECH.

10. Загрузка аккумулятора из порта N. Мнемоника команды:

    IN N

(от input - ввод).

Напоминаем, что команды ввода-вывода обращаются не к обычным ячейкам памяти. Они имеют дело скорее с внешними устройствами, наблюдать за которыми с помощью отладчика невозможно и даже опасно.

11. Загрузка порта N в аккумулятор. Мнемоника команды:

    OUT N

(от output - вывод).

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

Приступим к рассмотрению команд, пересылающих сразу по два байта. Многие из них схожи с перечисленными выше, но есть и новая, очень важная, подгруппа команд обеспечивающая использование стека - обмен со стеком, его загрузка, загрузка указателя стека SP. Кроме того, появляются команды, не только пересылающие, но и обменивающие значения.

Таблица 2. Двухбайтовые команды пересылки данных
N
п/п
Мнемоника Длительность
выполнения
(тактов)
Код Действие
12 LXI RR,NN 10 0 0 R R 0 0 0 1
N N N N N N N N
N N N N N N N N
Загрузка 16-разрядного числа в регистровую пару
13 LHLD NN 16 0 0 1 0 1 0 1 0
N N N N N N N N
N N N N N N N N
Пересылка 16-разрядного числа из ячеек памяти в регистровую пару HL
14 SHLD NN 16 0 0 1 0 0 0 1 0
N N N N N N N N
N N N N N N N N
Пересылка 16-разрядною числа из регистровой пары HL в память
15 PUSH QQ 11 1 1 Q Q 0 1 0 1 Пересылка содержимого регистровой пары в стек
16 POP QQ 11 1 1 Q Q 0 0 0 1 Пересылка 16-разрядного числа из стека в регистровую пару
17 SPHL 6 1 1 1 1 1 0 0 1 Пересылка содержимого HL в SF
18 XCHG 4 1 1 1 0 1 0 1 1 Обмен 16-разрядными числами между HL в DE
19 XTHL 12 1 1 1 0 0 0 1 1 Обмен содержимым между HL и стеком

12. Загрузка 16-разрядного числа в регистровую пару. Мнемоника команды:

    LXI RR,NN

Ее код состоит из трех байтов

    00RR0001
    NNNNNNNN
    NNNNNNNN

Первый байт определяет тип операции (биты 7, 6, 3, 2, 1, 0) и имя регистровой пары (биты 5 и 4). Пример:

    LXI Н,3210Н

или, в цифровом виде,

    00100001B=21H
    00010000B=10H
    00110010B=32H

загрузит в HL число 3210Н.

В мнемонике команды используется только имя старшего регистра пары, например, Н обозначает HL; однако SF обозначается полностью:

    LXI SP,NN

13. Пересылка 16-разрядного числа из ячеек памяти в регистровую пару HL:

    LHLD NN

(load HL direct - прямая загрузка в HL). При ее выполнении содержимое ячеек памяти с адресами NN и NN+1 пересылается в регистровую пару HL.

Посмотрим, что произойдет при выполнении команды

    LHLD 3678Н

или, в цифровом виде,

    00101010B=2AH
    01111000B=78H
    01010110B=56H

Пусть ячейка памяти 5678Н содержит число 01Н, а ячейка 5679Н - число 02Н. Тогда в HL запишется число 0201Н, т. е. в L будет храниться 01Н, а в Н - 02Н.

14. Пересылка 16-разрядною числа из регистровой пары HL в память:

    SHLD NN

(store HL direct). При выполнении, к примеру, команды

    SHLD 5678Н

или, в цифровом виде,

    00100010В=22Н
    01111000В-78Н
    01010110B-56H

содержимое регистра L помещается в ячейку памяти с адресом 5678Н, а содержимое Н - в ячейку с адресом 5679Н; если в HL хранилось число 1011Н, то в ячейке 5678Н будет записано 11Н, а в 5679H - 10Н.

Как вы, наверное, обратили внимание, во всех командах, имеющих отношение к 16-битным числам, сначала загружается младший байт числа (он обозначается LSB от англ. least significant byte - младший значащий байт), а потом уже старший (MSB - most significant byte - старший значащий байт). Это соглашение строго соблюдается во всех командах.

15. Пересылка содержимого регистровой пары в стек

Здесь прежде всего напомним, что хотя стек есть не какое-либо особенное устройство, а лишь особым образом используемая область ОЗУ, и обмен с его ячейками можно было бы выполнять и обычными командами, для обращения к нему всегда используется SP и только SP. Причина проста - в КР580ВМ80 аппаратно реализован механизм, "заставляющий" содержимое SP всегда указывать на вершину стека, т. е. то место в памяти, где находится "последний патрон".

Итак, команда

    PUSH QQ

(от push - толкать, отсюда и жаргонное "выталкивать в стек") пересылает в стек содержимое одной из регистровых пар ВС, DE, HL или AF (PSW), обозначенных в этой мнемонике QQ. Код команды:

    11QQ0101

Имя регистровой пары кодируется значениями битов 5 и 4 следующим образом:

При выполнении этой команды происходят довольно сложные действия. Рассмотрим процесс выталкивания в стек содержимого HL (обратите внимание, что в мнемонику входит только имя старшего регистра):

    PUSH H

Сначала содержимое регистра L помещается в ячейку памяти с адресом, равным содержимому регистра SP минус 2 (обозначим (SP)-2), а содержимое регистра Н - в ячейку с адресом (SP)-1; затем содержимое SP уменьшается на 2. Если в HL хранилось число 0102Н, а в SP - 9999Н, то после выполнения команды в ячейке 9998Н будет число 01Н, в ячейке 9997Н - число 02Н, а (SP) будет равно 9997Н; (SP) указывает на ячейку памяти с последним загруженным в стек числом.

Еще один пример. Пусть в аккумуляторе содержится число 55Н, в регистре флагов - 43Н, а в SP - 1005Н. После выполнения команды PUSH PSW в ячейке 1004Н будет число 55Н, в ячейке 1003Н - 43Н, а в SP - 1003Н.

16. Пересылка 16-разрядного числа из стека в регистровую пару:

    POP QQ

(не звук ли пробки, выскакивающей из бутылки, стал прообразом этой мнемоники?). При ее выполнении число из вершины стека (адрес которой всегда хранится в SP) помещается в регистровую пару, (SP) увеличивается на 2.

Попробуем выполнить команду

    POP H

Пусть в SP записано число 2345Н, в ячейке памяти с адресом (SP), т. е. 2345Н, записано ЗЗН, а в ячейке с адресом (SP)+1, т. е. 2346Н, записано 44Н. После выполнения команды в регистр L попадет ЗЗН, в Н - 44Н, а в SP будет храниться 2347Н; (SP) указывает на новую вершину стека.

17. Пересылка (HL) в SF

    SPHL

Содержимое регистровой пары HL просто копируется в регистр SP.

18. Обмен двухбайтными словами между регистровыми парами HL и DE:

    XCHG

(корявое сокращение слова exchange - обмен). То, что было в HL, попадет в DE, а то, что было в DE, попадет в HL.

19. Обмен содержимым между регистровой парой HL и стеком:

    XTHL

(возможно, от exchange top HL).

Допустим, что в SP хранилось число 1234Н; в вершине стека, т. е. в ячейках памяти с адресами 1234Н и 1235Н - числа ЗЗН и 22Н соответственно; в L - число 55Н; в Н - 44Н. Тогда после выполнения команды XTHL в ячейках памяти с адресами 1234Н и 1235Н будут храниться числа 55Н и 44Н соответственно, а в регистровой паре HL - число 2233Н. Содержимое SP не изменится.

На этом можно подвести черту под командами пересылки. Отметим, что на регистр флагов F воздействует только одна из них - POP PSW.

Приступим к рассмотрению арифметических и логических операций. Эта группа команд имеет особое значение, так как именно она позволяет производить обработку данных.

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

Логические операции - это поразрядные операции И, ИЛИ, ИСКЛЮЧАЮЩЕЕ ИЛИ и сравнение. Операнды, используемые в них, те же, что и в арифметических. Есть также команды, реализующие сдвиг аккумулятора влево и вправо и его побитное инвертирование.

Все арифметические и логические операции воздействуют на регистр флагов, поэтому уместно отнести к этой группе еще две команды - установки и инвертирования флага переноса.

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

Таблица 2. Двухбайтовые команды пересылки данных
N
п/п
Мнемоника Длительность
выполнения
(тактов)
Код Действие
20 ADI N 7 1 1 0 0 0 1 1 0
N N N N N N N N
Z, S, P, C, AC
Сложение содержимого аккумулятора и 8-разрядного числа
21 ADD R 4 1 0 0 0 0 R R R
Z, S, P, C, AC
Сложение содержимых аккумулятора и одного из регистров общего назначения
22 ADD M 7 1 0 0 0 0 1 1 0
Z, S, P, C, AC
Сложение содержимых аккумулятора и ячейки памяти, адресуемой через HL
23 ACI N 7 1 1 0 0 1 1 1 0
N N N N N N N N
Z, S, P, C, AC
Сложение содержимого аккумулятора (с учетом флага переноса) с 8-разрядным числом
24 ADC R 4 1 1 0 0 0 R R R
Z, S, P, C, AC
Сложение содержимых аккумулятора (с учетом флага переноса) и регистра общего назначения
25 ADC M 7 1 1 0 0 1 1 1 0
Z, S, P, C, AC
Сложение содержимых аккумулятора (с учетом флага переноса) и ячейки памяти, адресуемой через HL
26 SUI N 7 1 1 0 1 0 1 1 0
N N N N N N N N
Z, S, P, C, AC
Вычитание из содержимого аккумулятора 8-разрядного числа
27 SUB R 4 1 0 0 1 0 R R R
Z, S, P, C, AC
Вычитание из содержимого аккумулятора содержимого регистра общего назначения
28 SUB M 7 1 0 0 1 0 1 1 0
Z, S, P, C, AC
Вычитание из содержимого аккумулятора содержимого ячейки памяти, адресуемой через HL
29 SBI N 7 1 1 0 1 1 1 1 0
N N N N N N N N
Z, S, P, C, AC
Вычитание (с учетом флага переноса) из содержимого аккумулятора 8-разрядного числа
30 SBB R 4 1 0 0 1 0 1 1 0
Z, S, P, C, AC
Вычитание (с учетом флага переноса) из содержимого аккумулятора содержимого регистра общего назначения
31 SBB M 7 1 0 0 1 1 1 1 0
Z, S, P, C, AC
Вычитание (с учетом флага переноса) из содержимого аккумулятора содержимого ячейки памяти, адресуемой через HL
32 CPI N 7 1 1 1 1 1 1 1 0
N N N N N N N N
Z, S, P, C, AC
Сравнение содержимого аккумулятора и 8-разрядного числа
33 CMP R 4 1 0 1 1 0 R R R
N N N N N N N N
Z, S, P, C, AC
Сравнение содержимых аккумулятора и регистра общего назначения
34 CMP M 7 1 0 1 1 1 1 1 0
Z, S, P, C, AC
Сравнение содержимых аккумулятора и ячейки памяти, адресуемой через HL

20. Сложение содержимого аккумулятора и 8-разрядного числа:

    ADI N

(addition immediate - прямое сложение). В результате этой операции к содержимому аккумулятора прибавляется число N и результат сложения помещается в аккумулятор; кроме того, изменяется (F):

Рассмотрим пример. Пусть в аккумуляторе хранилось число 05Н. Тогда после выполнения команды

    ADI 21Н

будет (А)=26Н, (Z)=0, (S)=0, (Р)=0, (С)=0.

Действие арифметических и логических команд не столь очевидно, как команд пересылок, поэтому рекомендуем изучать их с помощью специальной программы-отладчика, например, SID или DDT (эти программы входят в состав пакета СР/М).

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

Реассемблирование - представление машинных кодов в виде последовательности мнемоник команд процессора. Формат команды:

L - реассемблирование с текущего указателя;

Laddress - реассемблирование с заданного указателя;

LaddressStart, addressEnd - реассемблирование с заданного по заданный указатель;

L,addressEnd - реассемблирование до заданного указателя.

Ассемблирование - исправление кода в мнемонике процессора. Формат команды:

Aaddress - ассемблирование с адреса (address).

После ввода этой команды отладчик ждет ввода команды в мнемонике процессора; получив ее, переводит в код и записывает с указанного адреса. Это он делает до тех пор, пока вы вводите правильные команды или не поставите точку.

Просмотр регистров и изменение содержимого регистров. Формат команды:

X - отладчик выводит содержимое всех регистров на экран;

Хрегистр - отладчик выводит содержимое указанного регистра на экран и ждет новое значение этого регистра. Если вы не желаете изменить содержимое регистра, просто нажмите клавишу ENTER.

Трассировка: пошаговое выполнение программы. Формат команды:

Т - выполнится одна команда, находящаяся по адресу, на который указывает счетчик команд.

Отметим, что все числа в отладчике вводятся и выводятся в шестнадцатеричном виде.

Рекомендуем следующую последовательность действий при изучении команд с помощью отладчика Перво-наперво, естественно, необходимо запустить программу. Затем:

1) с помощью команды ассемблирования ввести изучаемую команду, например:

    А100
    0100 ADI 21

2) установить регистр счетчика команд на адрес нашей команды:

    ХР
    Р=ХХХХ 100             (ХХХХ - текущее значение)

3) установить требуемые значения регистров, используемых в команде:

    ХА
    А=ХХ 5                 (XX - текущее значение)

4) убедиться, что все регистры установлены правильно:

    Х

Отметим, что в напечатанной строке справа отображена мнемоника текущей команды (в нашем примере - ADI 21);

5) выполнить одну команду:

    T

6) посмотреть результат:

    Х

Обратите внимание, как изменилось содержимое регистров и флагов. Попробуйте выполнить одну команду несколько раз с разными значениями используемых регистров и посмотрите, как будет меняться результат.

21. Сложение содержимого аккумулятора с содержимым одного из регистров общего назначения:

    ADD R КОД

код команды

    10000RRR

где RRR расшифровываются так же, как в команде MVI R,N (N° 1 в нашем списке).

Содержимое аккумулятора складывается с содержимым указанного регистра общего назначения, и результат помещается в аккумулятор; биты Z, S, Р и С регистра F устанавливаются так же, как в предыдущем случае. Например, если в А хранилось число 11Н, а в В - ЗЗН, то после выполнения операции ADD В в аккумуляторе будет число 44Н, (В) не изменится.

22. Сложение содержимого аккумулятора с содержимым ячейки памяти, адресуемой с помощью HL:

    ADD M

При выполнении этой команды (А) становится равным старому содержимому А, сложенному с (М); биты Z, S, Р и С регистра F устанавливаются так же, как в предыдущем случае.

Пусть (А)=22Н, (HL)=1234Н, (М)=ЗЗН. После выполнения команды ADD М содержимое HL и М (ячейки памяти с адресом 1234Н) не изменится, а (А) станет равным 55Н

Мы надеемся, что читатель уже немного привык к терминологии и не нуждается в слишком тщательном разжевывании материала, и будем далее объединять схожие команды для сокращения объема текста.

23-25. Сложение содержимого аккумулятора с учетом флага переноса. Операндами здесь могут быть: 8-разрядное число (addition with carry immediate - прямое сложение с учетом переноса);

    ACI N

регистр общего назначения (addition w.th carry - сложение с учетом переноса);

    ADC R

содержимое ячейки памяти с адресом, хранящимся в HL.

    ADC М

Результат выполнения - сумма соответствующего числа и содержимого аккумулятора, к которой прибавляется еще единица, если (С)=1. Результат записывается в аккумулятор. Влияние на регистр F такое же, как выше.

Рассмотрим примеры. Если (А)=22Н, (HL)=0FFFFH, в ячейке памяти с адресом 0FFFFH хранится число ЗЗН и (С) = 1, то после выполнения операции ADC М в А будет число 56Н. Если (А)=06Н, (Н)=0, а в результате какой-то прошлой операции флаг С был установлен в 1, то после выполнения операции ADC Н в аккумуляторе окажется число 07Н.

Перейдем теперь к вычитанию. Оно происходит аналогично: из содержимого аккумулятора вычитается некоторая величина, определяемая операндом команды, и результат сохраняется в аккумуляторе. Единственное изменение в терминологии касается переноса: в случае вычитания пользуются термином "заем".

26-28. Простое вычитание:

    SUI N

(subtraction immediate - прямое вычитание);

    SUB R

(subtraction - вычитание);

    SUB M

Воздействие на биты Z, S, Р регистра F, как в уже описанных командах, бит С устанавливается в 1, если в процессе вычитания был произведен заем из 7-го бита, и в 0, если не был.

Рассмотрим пример. Пусть (А)=66Н, (В)=21Н. В результате выполнения команды SUB В в А окажется число 45Н.

29-31. Вычитание с учетом переноса:

    SBI N

(subtraction with borrow immediate - прямое вычитание с учетом заема (переноса));

    SBB R

(subtraction with borrow - вычитание с учетом заема);

    SBB M

При выполнении этих команд из содержимого аккумулятора вычитается величина, определяемая операндом команды, а если флаг переноса установлен в 1, то вычитается еще 1. Воздействие на регистр F, как у предыдущих команд.

Пусть (А)=58Н, (HL)=3210H, в ячейке памяти с адресом 3210Н хранится число 42Н, (С) в результате предыдущих действий равен 1. Тогда после выполнения команды SBB М в аккумуляторе окажется число 15Н, содержимое ячейки памяти и HL останутся неизменными. А если (А)=32Н, (В)=11Н, (С)=1, то после выполнения операции SBB В в аккумуляторе окажется число 20Н.

32-34. Команды сравнения вычитают из содержимою аккумулятора операнд (число; содержимое регистра общего назначения; содержимое ячейки памяти с адресом, находящимся в HL), но полученное число не записывается в аккумулятор. Таким образом, все операнды команд остаются неизменными, а результатом выполнения является изменение содержимого регистра F.

Мнемоники команд:

    CPI N

(compare immediate - прямое сравнение);

    CMP R

(compare - сравнивать);

    CMP N

Содержимое регистра флагов меняется обычным образом:

Z устанавливается в 1, если результат вычитания равен 0, и в 0, если результат не равен 0;

S - в 1, если результат отрицательный,и в 0, если положительный;

Р - в 1, если в битах результата четное число единиц, и в 0, если оно нечетное;

С - в 1 если в процессе вычитания был произведен заем из 7-го бита, и в 0, если не было.

Рассмотрим примеры. Пусть (А)=51Н, (HL)=1234H, в ячейке памяти с адресом 1234Н хранится число 52Н. Тогда результатом выполнения операции CMP М будет установление следующих значений битов регистра F: (Z)=0, (S)=1, (Р)=0, (С)=1. (A), (HL) и содержимое ячейки 1234Н не изменяются.

Если (А)=63Н, (В)=63Н, то после выполнения команды СМР В флаги будут иметь значения (Z)=1, (S)=0, (P)=0, (C)=0.

Настала очередь логических операций. Они оперируют с отдельными битами числа. Наиболее известные из них - AND (И), OR (ИЛИ). Результат логической операции определяется ее таблицей истинности. Приведем эти таблицы.

    1 AND 1 = 1          1 OR 1 = 1
    1 AND 0 = 0          1 OR 0 = 1
    0 AND 1 = 0          0 OR 1 = 1
    0 AND 0 = 0          0 OR 0 = 0

Еще одна логическая операция, реализованная в К580ВМ80,- XOR (исключающее ИЛИ). Это, по сути, сложение по модулю 2:

    1 XOR 1 = 0
    1 XOR 0 = 1
    0 XDR 1 = 1
    0 XOR 0 = 0

Выполнением логической операции с байтом считается ее выполнение с каждым из битов байта.

В качестве одного из операндов обязательно используется как и в арифметических операциях, аккумулятор; в качестве другого операнда может выступать, как и прежде, явно заданное 8-разрядное число, либо содержимое регистра общего назначения, либо содержимое ячейки памяти, адресуемой с помощью HL.

Таблица 2. Двухбайтовые команды пересылки данных
N
п/п
Мнемоника Длительность
выполнения
(тактов)
Код Действие
35 ANI N 7 1 1 1 0 0 1 1 0
N N N N N N N N
Z, S, P, C, AC
Логическое умножение содержимого аккумулятора на 8-разрядное число
36 ANA R 4 1 0 1 0 0 R R R
Z, S, P, C, AC
Логическое умножение содержимых аккумулятора и регистра общего назначения
37 ANA M 7 1 0 1 0 0 1 1 0
Z, S, P, C, AC
Логическое умножение содержимых аккумулятора и ячейки памяти, адресуемой черев HL
38 ORI N 7 1 1 1 1 0 1 1 0
N N N N N N N N
Z, S, P, C, AC
Логическое сложение содержимого аккумулятора с 6-разрядным числом
39 ORA R 4 1 0 1 1 0 R R R
Z, S, P, C, AC
Логическое сложение содержимых аккумулятора и регистра своего назначения
40 ORA M 7 1 0 1 1 0 1 1 0
Z, S, P, C, AC
Логическое сложение содержимых аккумулятора и ячейки памяти, адресуемой через HL
41 XRI N 7 1 1 1 0 1 1 1 0
N N N N N N N N
Z, S, P, C, AC
Операция "исключающее или" над содержимым аккумулятора и 8-разрядным числом
42 XRA R 4 1 0 1 0 1 R R R
Z, S, P, C, AC
Операция "исключающее или" над содержимыми аккумулятора и регистра общего назначения
43 XRA M 7 1 0 1 0 1 1 1 0
Z, S, P, C, AC
Операция "исключающее или" над содержимыми аккумулятора и ячейки памяти, адресуемой черев HL

35-37. Логическое умножение (AND):

    ANI N

(AND immediate);

    ANA R
    ANA M

При выполнении этих команд происходит побитное логическое умножение (операция И) содержимого аккумулятора с числом, определяемым операндом. Результат записывается в аккумулятор. Флаг Z принимает значение 1. если результат равен 0, и 0, если не равен; S - 1, если результат отрицательный, 0 - если положительный; Р и С - как сказано выше.

Пусть в аккумуляторе хранится число В9Н=10111001В. Тогда при выполнении операции ANI 85Н (85Н=10000101В) мы получим результат 10000001В=81Н, который и будет записан в аккумулятор.

38-40 Логическое сложение (OR):

    ORI N 
    ОRА R 
    ORA M

Команды выполняют побитное логическое сложение содержимого аккумулятора и операнда. Воздействие на флаги аналогично команде AND.

Пусть в аккумуляторе содержится число 82Н, а в регистре С - 98Н; тогда после выполнения операции ORA С в аккумуляторе окажется число 9АН.

41-43. "Исключающее ИЛИ":

    XRI N 
    XRA R 
    XRA М

Команды выполняют побитно операцию XOR между содержимым аккумулятора и операнда. Воздействие на флаги аналогично команде AND.

Пусть в аккумуляторе записано число 13Н=00010011В, а в регистре D - число 25Н=00100101В. Тогда после выполнения операции XRA D в аккумуляторе будет храниться число 36Н=00110110В.

Перейдем теперь к довольно специфической группе арифметических операций - инкрементам и декрементам, иначе говоря, операциям увеличения или уменьшения на 1. Операндом в них может быть регистр общего назначения, либо ячейка памяти с адресом, хранящимся в HL, либо регистровая пара ВС, DE, HL, либо регистр SP.

Таблица 2. Двухбайтовые команды пересылки данных
N
п/п
Мнемоника Длительность
выполнения
(тактов)
Код Действие
44 INR R 5 0 0 R R R 1 0 0
Z, S, P, C, AC
Увеличение содержимого регистра на 1
45 INR M 10 0 0 1 1 0 1 0 0
Z, S, P, C, AC
Увеличение содержимого ячейки памяти, адресуемой через HL, на 1
46 DCR R 5 0 0 R R R 1 0 1
Z, S, P, C, AC
Уменьшение содержимого регистра на 1
47 DCR M 10 0 0 1 1 0 1 0 1
Z, S, P, C, AC
Уменьшение содержимого ячейки памяти, адресуемой через HL, на 1
48 INX RR 5 0 0 R R 0 0 1 1 Увеличение содержимого регистровой пары на 1
49 DCX RR 5 0 0 R R 1 0 1 1 Уменьшение содержимого регистровой пары на 1
50 DAD RR 10 0 0 R R 1 0 0 1
C
Сложение содержимого HL с одной из регистровых пар
51 RRC 4 0 0 0 0 1 1 1 1
C
Сдвиг содержимого аккумулятора вправо простой
52 RAR 4 0 0 0 1 1 1 1 1
C
Сдвиг содержимого аккумулятора вправо черев бит С
53 RLC 4 0 0 0 0 0 1 1 1
C
Сдвиг содержимого аккумулятора влево простой
54 RAL 4 0 0 0 1 0 1 1 1
C
Сдвиг содержимого аккумулятора влево через бит С
55 СМС 4 0 0 1 1 1 1 1 1
C
Инвертирование флага С
56 STС 4 0 0 1 1 0 1 1 1
C
Установка флага С в 1
57 CMA 4 0 0 1 0 1 1 1 1 Инвертирование содержимого аккумулятора
58 DAA 4 0 0 1 0 0 1 1 1
Z, S, Р, С, АС
Приведение двоичного числа к двоично-десятичному представлению

44-45. Увеличение 8-разрядного операнда на 1:

    INR R

(increment - увеличение);

    INR М

На флаги эти операции воздействуют следующим образом:

Z устанавливается в 1, если результат равен 0, и в 0, если не равен;

S - в 1, если результат отрицательный, в 0 - если положительный;

Р - в 1, если число битов результата, установленных в 1, четное, и в 0 - в противном случае;

С - не меняется.

Рассмотрим пример. Если в (А)=35Н, то после выполнения операции INR А в А будет храниться число 36Н.

46-47. Уменьшение 8-разрядного операнда на 1:

    DCR R

(decrement - уменьшать);

    DCR М

Действие на регистр флагов такое же, как в предыдущем случае.

Пусть (HL)=3333H, а в ячейке памяти с адресом ЗЗЗЗН хранится число 59Н. Тогда после выполнения команды DCR М в ячейку памяти с адресом ЗЗЗЗН будет записано число 58Н; содержимое регистровой пары HL не изменится.

Перейдем к командам 16-разрядной арифметики. Их всего три типа: инкремент, декремент и сложение (HL) с содержимым других регистровых пар.

48. Увеличение содержимого регистровой пары на 1:

    INX RR

В коде команды

    00RR0011

используемая регистровая пара обозначается следующим образом:

Таким образом, код команды INX Н равен 00100011В=23Н, и если в HL хранилось число 3321Н, то после выполнения команды там будет записано число 3322Н.

На флаги команда не воздействует.

49. Уменьшение содержимого регистровой пары на 1:

    DCX RR

50. Сложение содержимого регистровой пары HL с одним из регистров ВС, DE, HL, SP

    DAD RR

Команда воздействует на флаг С. Он становится равным 1, если был перенос из 15-го бита, и 0, если переноса не было.

Рассмотрим в качестве примера сложение (HL) и (DE). Для этого выполним команду DAD D. Если в HL было записано число 1234Н, а в DE - 4321Н, то после выполнения команды в HL окажется число 5555Н.

В арсенале вычислительных средств К580ВМ80 есть совсем уж необычные с точки зрения привычной арифметики команды: сдвиги. При сдвиге содержимое всех битов числа перемещается на одну позицию вправо или влево, так что при сдвиге вправо содержимое бита 1 попадает в бит 0, содержимое бита 2 - в бит 1 и т. д. Содержимое бита 0 попадает в бит С регистра F и, быть может, в бит 7; а может быть, в бит 7 попадет содержимое бита С. Это зависит от вида команды. Команды простого сдвига как бы сворачивают байт в кольцо. Перемещая содержимое битов на одну позицию вправо или влево, они еще и дублируют бит. переходящий через "место склейки" кольца, в бит С. Команды же сдвига через бит С "вставляют" бит С в "место склейки" кольца-байта, так что он служит не только приемником, но и источником информации.

Тест на понимание: объясните, почему сдвиг влево эквивалентен умножению байта на два, а сдвиг вправо - это, по сути, целочисленное деление на 2.

51-52. Сдвиг вправо содержимого аккумулятора. Таких команд две - простой сдвиг и сдвиг через бит С:

    RRC

(rotate right circular - вращение вправо циклическое);

    RAR

Пусть, для примера, (А)=10110111 В, (С)=0. После выполнения команды RRC в аккумуляторе окажется число 11011011В, а С примет значение 1. А если бы мы выполнили команду RAR, то флаг С также принял бы значение 1, но в аккумуляторе оказалось бы число 01011011.

53-54. Сдвиг влево содержимого аккумулятора:

    RLC

(rotate left circular - вращение влево циклическое);

    RAL

Попробуем повращать аккумулятор, записав в него число 01110011, если флаг С равен 1. При выполнении команды RLC в аккумуляторе окажется число 11100110, (С)=0; при выполнении команды RAL в аккумуляторе окажется число 11100111, (C)=0.

Наконец, четыре последние команды из группы арифметических и логических.

55. Инвертирование флага С:

    CMC

(complement carry - дополнение флага переноса). При выполнении этой команды С становится равным 0, если был равен 1, и 1, если был равен 0. Старое значение С переписывается в бит АС регистра F.

56. Установка флага С в 1:

    STC

(set carry - установить флаг переноса). При выполнении этой команды флаг С устанавливается в 1, а флаг АС - в 0.

57. Инвертирование содержимого аккумулятора:

    СМА

(complement accumulator - дополнение аккумулятора). Эта команда инвертирует все биты аккумулятора. Если (А)=01100011, после выполнения команды СМА в аккумуляторе окажется число 10011100.

58. Команда десятичной поправки, появившаяся как результат существования двух представлений двоичных чисел. Кроме обычного, с которым мы постоянно имеем дело, существует еще двоично-десятичное представление: цифрами 0 и 1 кодируются цифры десятичного представления числа, а не само число. Иначе говоря, байт разбивается на 4-разрядные половинки, в каждую из которых разрешается записать двоичное число без знака, не превышающее 9. Таким образом можно кодировать десятичные числа от 0 до 99.

Чтобы перевести число из двоичного в двоично-десятичное представление, нужно к тем из его 4-разрядных половинок, содержимое которых превышает 9, прибавить число 6 (0110В). Разумеется, если возникает перенос, то его тоже нужно прибавить. Эту процедуру и выполняет команды.

    DAA

(decimal adjust accumulator - добавление к аккумулятору десятичного остатка). Оперирует она, как следует из названия, с числом, находящимся в аккумуляторе.

Поскольку с двоично-десятичными (BCD - binary-decimal digit) числами мы пока не встречались, поупражняемся.

Допустим, мы хотим сложить числа 13 и 28. Результат известен - 41. Однако если мы закодируем их в двоично-десятичном виде (1D=0001B, 3D=0011B, 13D=00010011BCD; 2D=0010B, 8D=1000B, 28D=00101000BCD) и сложим, то...

    00010011BCD
   +
    00101000BCD
    --------
    00111011B=3BH

ЗВН не является BCD-числом. Для приведения его в "правильный" вид исполним команду DAA, т. е. прибавим к каждой 4-разрядной половине байта, в которой записано число, превышающее 9, число 6. В нашем случае необходимо прибавить 6 к "младшей" половине:

    00111011В
   +
    00000110В
    --------
    01000001BCD=41D

Результат правильный.

Эта команда воздействует на флаги следующим образом:

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

Следующая важная группа - команды управления работой программы. Что это за команды? Любая программа реализует какой-то алгоритм. Часто используемым элементом алгоритма является проверка каких-либо условий и в зависимости от результатов проверки выполнение того или иного фрагмента программы. Команды управления работой программы несут в себе эту функцию.

Кроме того, редко, когда программа пишется как единое целое. С ростом ее объема становится все труднее и труднее в ней разобраться. К тому же в программе неизбежно появляются некоторые совокупности операций, которые необходимо выполнять в самых разнообразных местах программы. Обычно, такие совокупности операций называются подпрограммами, или функциями. Естественно, напрашивается решение разбить программу на мелкие части и обращаться к этим частям по мере надобности. Команды вызова подпрограмм и возврата из них также относятся к командам управления работой программы. Разберемся, что делают эти команды.

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

Обращение к подпрограммам или другим частям программы требует нарушения размеренной жизни процессора и памяти. В этом случае говорят о передаче управления. При этом содержимое PC изменяется таким образом, чтобы соответствовать адресу первой команды подпрограммы.

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

1. Команда безусловного перехода. Эта команда состоит из 3-х байтов. Первый - код команды, а два других - адрес того места, куда нужно передать управление. Мнемоника команды:

    JMP NN

происходит она от англ, jump - прыгать. Как только процессор получает эту команду, он без лишних раздумий загружает число NN в регистр PC, и дальнейшее от него уже не зависит. Следующая команда будет считана из ячейки памяти с адресом NN.

Обратите внимание, что адрес того места, откуда совершается прыжок, нигде не записывается и, следовательно, сам процессор без нашей помощи его не найдет. Код команды имеет вид:

    1 1 0 0 0 0 1 1
    N N N N N N N N
    N N N N N N N N

Причем, второй байт команды соответствует младшему байту адреса, а третий - старшему.

Команда выполняется за 10 тактов, т. е. за 4 мкс. На флаги эта команда не действует. Мы научились путешествовать по программе, приказывая процессору прыгать в том или ином направлении по заданному адресу. Но этого слишком мало. Как найти выход из ситуации, когда надо переходить лишь при выполнении определенного условия? С помощью безусловных переходов тут ничего не сделаешь. Чтобы помочь нам в решении подобных проблем, в составе команд процессора есть команды переходов при выполнении условия.

Вопрос на сообразительность. Где в процессоре может храниться информация о выполнении условий? Сообразительные могут следующее предложение не читать. Для остальных скажем: в регистре флагов. Итак, переходы по условию.

2. Команды переходов по условию. Спектр условий, имеющихся в нашем распоряжении, не слишком богат. В условных переходах используются 4 флага Z, S, Р, С. Соответственно получается 8 условий:

Мнемоника команды условного перехода образуется из объединения буквы J - от jump и сокращенного обозначения условия, приведенного выше. Так, например, команда перехода, если Z=1, имеет вид JZ NN, где NN, как и в случае безусловных переходов, суть адрес того места в программе, куда передается управление. Код этих команд занимает три байта:

    1 1 с с с 0 1 0 
    N N N N N N N N 
    N N N N N N N N

где 3, 4 и 5 биты первого байта кодируют тип условия:

    с  с  с
    0  0  0 NZ
    0  0  1 Z
    0  1  0 NC
    0  1  1 C
    1  0  0 РО
    1  0  1 РЕ
    1  1  0 Р
    1  1  1 М

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

Хотя эти команды пользуются регистром флагов, но его содержания не изменяют. Рассмотрим пример. Пусть содержимое С флага равно 1. Тогда после выполнения команды

    JC 1221Н

в регистре PC окажется число 1221Н и в следующем машинном цикле процессор начнет считывать команду, первый байт которой находится по адресу 1221Н.

Выполняются эти команды за 10 тактов, т. е. за 4 мкс.

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

3. Команда вызова подпрограммы. Мнемоника команды:

    CALL NN

и происходит от английского call - звать, операнд NN - соответствует адресу новой команды подпрограммы. При выполнении этой команды процессор загружает в регистр PC число NN и таким образом происходит передача управления. Но это не все. Дело в том, что при выполнении команды CALL текущее содержимое регистра PC записывается в область памяти стека (т. е. автоматически происходит операция PUSH PC). Другими словами, содержимое PC укладывается в верхушку стека: старший байт в ячейку памяти с адресом SP-1, младший байт в ячейку памяти SP-2. Здесь SP обозначает содержимое регистра SP-указателя стека. Само же это содержимое уменьшается на 2. Код команды занимает три байта.

    1 1 0 0 1 1 0 1
    N N N N N N N N
    N N N N N N N N

Выполняется команда за 17 тактов, т. е. за 6,8 мкс. Рассмотрим пример. Пусть в PC хранилось число 1234Н, в SP было записано 4321Н, а в ячейках памяти с адресами 1234Н, 1235Н и 1236Н были записаны байты

    CDH
    01Н
    23Н

Тогда в начале выполнения команды процессор считает ее код из ячейки 1234Н Это код CDH. Процессор сразу поймет, что это код команды CALL и считает еще 2 байта - адрес подпрограммы. Таким образом, в регистре PC окажется число 2301Н - адрес следующей команды в программе. Мнемоника команды:

    CALL 2301Н

Процессор поместит в PC новый адрес 2301Н, а в верхушку стека старое содержимое PC. Это значит, что в ячейку памяти с адресом 4320Н попадет байт 12Н, а в ячейку памяти 431FH - байт 37Н. В регистр SP будет записано число 431FH. (Напоминаем, если в действии команды что-то непонятно, надо ее изучить с помощью отладчика.)

Таким образом, процессор сохранил адрес того места в программе, куда нужно возвратить управление после выполнения подпрограммы. Для того чтобы это сделать, необходимо следить за состоянием регистра SP (особенно при пользовании командами PUSH и POP). Так, к моменту возврата из подпрограммы содержимое SP должно быть тем же, что и в начале ее выполнения. Несоблюдение этого требования может привести к "зависанию" машины.

Теперь рассмотрим процедуру возвращения из подпрограммы.

4. Команда возвращения из подпрограммы. Мнемоника команды происходит от англ, return, что означает возвращение, и имеет вид RET. Код команды:

    1 1 0 0 1 0 0 1

При выполнении команды возврата процессор извлекает из верхушки стека адрес того места в программе, откуда вызывалась подпрограмма. Младший байт адреса считывается из ячейки памяти с адресом, равным содержимому SP, а старший байт из ячейки памяти с адресом SP+1. При этом содержимое SP увеличивается на 2. После этого считанный из верхушки стека адрес записывается в PC и тем самым происходит передача управления. Команда выполняется за 10 тактов, т. е. за 4 мкс. Если внимательно посмотреть на действие этой команды, видно, что ее можно было бы назвать POP PC.

Рассмотрим пример. Пусть в регистре PC был записан адрес 3456Н. В SP хранится число 7000Н. В ячейках памяти с адресами 7000Н и 7001Н - байты 18Н и 01Н соответственно. После выполнения команды RET в PC будет записано число 0118Н в SP 7002Н и управление будет передано по адресу 0118Н, откуда и будет считана следующая инструкция. Наверное, вы уже начинаете понимать преимущества команд CALL и RET в организации подпрограмм. Нужно заметить, что это еще не все. В состав команд процессора входят также команды вызова подпрограмм и возврата из них по условию. Рассмотрим эти команды.

5. Команды вызова подпрограмм по условию. Эти команды выполняют передачу управления подпрограммам при выполнении указанного в коде команды условия. Условия имеют точно такой же вид, что и в случае команд jump.

Мнемоника рассматриваемых команд образуется из объединения буквы С (call) и мнемонического обозначения условия. Например, CZ NN - вызвать подпрограмму по адресу NN, если Z флаг равен 1. В целом, образование мнемоники аналогично случаю с условными переходами. Так и код команды занимает три байта:

    1 1 c c c 1 0 0
    N N N N N N N N
    N N N N N N N N

где биты 3, 4, 5 первого байта кодируют тип условия. Это кодирование осуществляется' аналогично случаю с условными, переходами. Выполняется эта команда следующим образом. Сначала процессор анализирует условие. Если оно выполнено, то 2 байта операнда команды загружаются в регистр PC и таким образом передается управление, а его старое содержимое перемещается в верхушку стека: в ячейку памяти с адресом SP-1 - старший байт, в ячейку с адресом SP-2 - младший. Само содержимое SP уменьшается на 2. Если условие не выполняется, то считывается следующая по порядку команда в программе.

Выполняются команды: за 17 тактов, т. е. за 6.8 мкс, если условие выполнено, и за 10 тактов, т. е. за 4 мкс, если - не выполнено. Рассмотрим пример. Если в PC хранилось число 1000Н, в регистре SP 5007Н, С флаг равен 1, то при выполнении команды СС 1234Н в PC окажется число 1234Н, в ячейке памяти с адресом 5006Н - байт 10Н, в ячейке 5005Н - байт 0ЗН, в SP будет записано число 5005Н. В результате управление будет передано подпрограмме, находящейся по адресу 1234Н. На состояние флагов рассмотренные команды не влияют. Коль скоро мы вызвали подпрограмму по условию, попробуем вернуться из нее по условию же.

6. Команды возврата из подпрограммы по условию. Мнемоника этих команд образуется аналогично рассмотренным условным переходам и вызовам. Мнемоника условий та же, только меняется первая буква. Теперь это не J и не С, a R (return). Так мнемоника команды возврата при условии С флаг равен 1 имеет вид:

    RC

Кодируются эти команды так же, как и выше рассмотренные:

    1 1 c c c 0 0 0

биты 3, 4 и 5 задают по известным нам правилам код условия. Выполняются эти команды за 11 тактов, т. е. за 4.4 мкс, если условие выполняется, и за 5 тактов, т. е. за 2 мкс, если - не выполняется.

Рассмотрим пример. Если S флаг был равен 1, в регистре SP было число 6000Н, в PC - 1111Н, в ячейке памяти с адресом 6000Н находится байт 18Н, в ячейке с адресом 6001Н - байт 25Н, то после выполнения команды

    RM

в PC будет загружено число 2518Н, в SP число 6002Н и управление таким образом будет передано по адресу 2518Н.

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

7. Команды рестарта. Мнемоника команды имеет вид:

    RST р

Число р указывает, по какому адресу передается управление. Р принимает значение от 0 до 7, что соответствует адресам 00Н, 08Н, 10Н, 18Н, 20Н, 28Н, З0Н, 38Н, которые кодируются с помощью битов 3, 4, 5 и код# ком№ды. Код имеет вид

    1 1 t t t 1 1 1

Биты 5, 4, 3 кодируют значение Р следующим образом

    а д р е с       P
    0 0 0 0 Н     0 0 0
    0 0 0 8 Н     0 0 1
    0 0 1 0 Н     0 1 0
    0 0 1 8 Н     0 1 1
    0 0 2 0 Н     1 0 0
    0 0 2 8 Н     1 0 1
    0 0 3 0 Н     1 1 0
    0 0 3 8 Н     1 1 1

При выполнении этой команды процессор записывает в верхушку стека содержимое PC старший байт в ячейку памяти с адресом SP-1 младший байт по адресу SP-2, а в PC загружает адрес в соответствии с номером рестарта. Содержимое SP уменьшается на 2.

Команда выполняется за 11 тактов, т. е. за 4.4 мкс.

Рассмотрим пример. Пусть в PC хранилось число 1234Н,. в SP число 8005Н. Тогда после выполнения команды

    RST 7

код которой 11111111В хранился по адресу 1234Н, в PC окажется число 0038Н, в SP - число 8003Н в ячейке памяти с адресом 8004Н число 12Н, в ячейке с адресом 8003Н - байт 35Н. Почему не 34Н, догадайтесь сами. Возвратиться из подобной процедуры можно по команде RET.

Рассмотрим теперь несколько иной способ передачи управления. Необходимость в нем возникает в случае наличия у программы нескольких входных точек, адрес которых заранее неизвестен. Например, это наблюдается в программе BIOS - управляющей работой железа, входящего в состав компьютера. У этой программы несколько входов. Один для работы при первом включении компьютера, второй при перезагрузке и т. д. При этом точно известен адрес только одного входа - остальные надо вычислять. Для организации подобной процедуры можно использовать команду RET, предварительно вычислив адрес входа в подпрограмму и записав его в стек. Однако наш процессор имеет более удобную для этой цели команду.

8. Команда безусловного перехода по адресу, указанному в регистровой паре HL. Мнемоника этой команды отвечает скорее обозначению процесса загрузки содержимого HL в регистр PC

    PCHL

При выполнении этой команды процессор переписывает содержимое HL в регистр PC. Таким образом, происходит передача управления. Код команды состоит из одного байта:

    1 1 1 0 1 0 1 1

Выполняется команда за 4 такта, т. е. за 1.6 мкс.

Наконец, последняя группа команд - команды управления работой процессора. Эти команды называют по-разному. Например, специальными. Их лучше не применять, не понимая работы компьютера. В противном случае вы можете завесить его так, что придется производить холодный старт. Рассмотрим эти команды.

1. Команда разрешения прерывания. Мнемоника команды:

    EI

от англ. Enable Interrupt (разрешение прерывания). Команда воздействует на триггер разрешения прерывания (процесс прерывания мы рассматривали выше), точнее, устанавливает его в .состояние "1".

Код этой команды равен

    1 1 1 1 1 0 1 1

Выполняется команда за 4 такта, т. е. за 1,6 мкс. На флаги эта команда не воздействует.

2. Команда запрещения прерывания. Мнемоника команды: DI

    DI

от англ. Disable Interrupt (запрещение прерывания). Действие этой команды противоположно предыдущей - она сбрасывает триггер разрешения прерываний.

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

Что будет дальше, не трудно сообразить. Код этой опасной, сугубо специальной команды:

    1 1 1 1 0 0 1 1

Выполняется она за 4 такта, т. е. за 1,6 мкс и на регистр флагов не воздействует.

3. Команда остановки процессора. Мнемоника этой" команды происходит от англ, halt - остановить:

    HLT

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

    0 1 1 1 0 1 1 0

Выполняется она за 4 такта, т. е. за 1,6 мкс, после чего машина зависает. На флаги команда не воздействует.

4. Команда пустышка. Эта команда хотя и выполняется процессором, но при этом ничего не происходит, кроме течения времени. Поэтому эту команду часто используют для задержки работы процессора до какого-либо события. Мнемоника команды имеет вид:

    NOP

что происходит от англ. No OPeration - нет операции. Код этой команды:

    0 0 0 0 0 0 0 0

"из ничего и выйдет ничего". Эта команда отвлекает процессор от нормальной работы на 4 такта, т. е. 1,6 мкс. Поскольку эта команда вообще ни на что не влияет, то в этом смысле флаги не являются исключением. Рассмотрим пример. Пусть в аккумуляторе содержится байт 08Н, в регистровой паре HL - 0010Н, а в регистре SP - 1111Н. После выполнения команды

    NOP

в аккумуляторе будет по-прежнему 08Н, в HL - 0010Н, а в SP - 1111Н. Вопрос на сообразительность, в каком же регистре изменилось содержимое? Ответ: в PC. На этой полезной команде мы закончим рассмотрение команд нашего процессора.