Архитектура процессора КР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).
TODO: ЗДЕСЬ БУДЕТ РИСУНОК 1Рисунок 1. Регистры
С одним регистром мы уже познакомились под именем указателя команды - это PC (от Program Counter - программный счетчик). Он является 16-разрядным, хранит адрес ячейки, содержащей следующую команду, которую процессор должен выполнить. Когда процессор извлекает из памяти очередное распоряжение, содержимое PC автоматически увеличивается на 1; таким образом процессор готовится извлечь из памяти следующую команду. При подаче на процессор сигнала СБРОС (его нельзя подать с помощью программы, обычно для этого служит специальная кнопка) или при включении питания содержимое PC всегда устанавливается в 0, что обеспечивает определенность состояния процессора при первоначальном запуске (включении питания).
Некоторые команды могут "напрямую" изменять содержимое PC, что бывает необходимо при выполнении условных и безусловных переходов. Позднее мы их внимательно изучим. Все они относятся к группе команд управления работой программы.
Отдельные биты регистра флагов независимы друг от друга. Они устанавливаются в 1 или сбрасываются в 0 в соответствии с результатами некоторых операций процессора (арифметических, логических и др.). Назначение битов регистра флагов показано на рис. 2.
TODO: ЗДЕСЬ БУДЕТ РИСУНОК 2Рисунок 2. Регистр флагов
Прочитать "в лоб" регистр флагов также нельзя - о состоянии его битов можно узнать только косвенно, по результатам работы команд условных переходов (о них мы расскажем чуть позже).
Регистр флагов при операциях со стеком образует с аккумулятором 16-разрядное слово, причем содержимое аккумулятора становится старшим, а регистр флагов - младшим байтом этого слова. Эта пара обозначается PSW (Processor State Word - слово состояния процессора). Благодаря этому записать и считать регистр флагов в явном виде все-таки можно, используя стек (подробнее об этом будет рассказано позже).
Кроме описанных выше регистров в процессоре имеется еще одно устройство, доступное программисту, - триггер разрешения прерывания. Работа с прерываниями имеет очень большое значение, поэтому остановимся немного на этой теме.
В повседневной жизни прерывания (правда, называем мы их обычно иначе) возникают очень часто. Вы готовите уроки (или завтрак); звонит телефон. Если вы отвлеклись от разговора, а потом вернулись к прерванному занятию, то этим в точности смоделировали компьютерное прерывание, т. е. переход по внешнему сигналу от одного дела к другому с последующим возвратом к первоначальному.
Источником прерывания послужил звонок телефона. Благодаря этому устройству вы сразу узнаете, что кто-то хочет связаться с вами. Представьте, что звонка нет (или он неисправен). Тогда, чтобы узнать, "звонит" кто-нибудь или нет, придется каждую минуту поднимать телефонную трубку и слушать. Человек на такое вряд ли согласится, а вот компьютеру приходится. Несмотря на кажущуюся абсурдность, этот способ ожидания событий (он называется опросом, по-английски polling) используется довольно часто для организации общения процессора со сравнительно медленно работающими периферийными устройствами, например клавиатурой и принтером.
Недостатки опроса очевидны. Из-за малого КПД (сотни проверок "на всякий случай"!) он отнимает значительное время у основной программы, хуже того - усложняет алгоритм ее работы. Ведь чтобы не пропустить нужное событие, мы должны "натыкать" блоки опроса в разные части программы.
Так что при введении механизма прерываний, несмотря на кажущееся усложнение (приходится изучать и использовать новые, дополнительные средства), программа, как правило, значительно упрощается, ее характеристики улучшаются и (на первый взгляд это может показаться странным) она начинает работать надежнее.
Расскажем о прерываниях подробнее. Предположим, что дополнительно к исполнению основной программы (пусть это будет война с космическими негодяями) компьютер должен отображать в углу экрана текущее время. Эти две задачи (игра и отображение времени) не связаны между собой. Игра - непрерывный процесс; реализующая ее программа должна перемещать какие-то объекты по экрану, реагировать на клавиши и т. д. Программа, имитирующая часы, должна следить за временем и каждую минуту обновлять показания на экране. Ясно, что ей не обязательно работать постоянно. Достаточно, если она будет включаться каждую секунду для увеличения счетчика и, если настала пора, вывода новых цифр на экран.
Для организации этого процесса используем электронный таймер, отсчитывающий время и подающий раз в секунду сигнал, который и будет событием, включающим программу-часы.
Прерывание реализуется на аппаратном уровне. Чтобы вызвать его, нужно подать сигнал (он называется запросом прерывания) на специальный вывод процессора. После этого, если так называемый триггер разрешения прерывания установлен (прерывания разрешены), процессор начинает цикл прерывания.
Он состоит из следующих операций. Сначала вместо считывания очередной команды основной программы из специального устройства, называемого контроллером прерываний, считывается команда вызова подпрограммы обработки прерываний (содержимое регистра PC при этом не изменяется). Выполняя ее, процессор запоминает адрес очередной команды текущей программы (т. е. содержимое PC) и передает управление программе, которая должна выполняться в связи с прерыванием - в нашем случае программе часов. Эта программа должна сохранить где-нибудь значения тех регистров процессора, которые она собирается изменить; выполнить свою основную задачу (увеличить значение счетчика, вывести на экран цифры); восстановить старые значения регистров, которые она использовала. Ее последней командой должна быть команда выхода из подпрограммы; она восстановит значение PC и тем самым возвратит управление основной программе, которая продолжится, как ни в чем ни бывало.
Описание конструкции процессора почти окончено, осталось упомянуть о способах общения с УВВ. В "Корвете" этим устройствам отводится часть ОЗУ, через которую процессор и обменивается данными с внешним миром; можно действовать и иначе - КР580ВМ80 имеет специальное адресное пространство ввода-вывода (отделенное от обычного 64-килобайтного) размером в 256 байтов. Ячейки этого пространства называются портами - видимо, чтобы подчеркнуть их роль "ворот" для связи, а также чтобы не путать с ячейками обычной памяти.
Команды КР580ВМ80
Разобравшись со структурой процессора, перейдем к описанию команд. В памяти они записываются, естественно, двоичными числами, но программисты практически всегда обозначают их буквенными аббревиатурами, так называемыми мнемониками. Мнемоники достаточно просто перевести в двоичные коды: "в жизни" переводом занимается транслятор-ассемблер, но можно произвести эту операцию и вручную. Мы будем приводить двоичные коды команд: знание лишним не бывает.
Что-то, возможно, будет вам непонятно; не переживайте. После основных сведений о командах пойдет рассказ об их использовании, и в нем по мере надобности будут разъясняться запутанные вещи. Впрочем, не обязательно дожидаться разъяснений: воспользуйтесь отладчиком (DDT или SID; входят в пакеты СР/М и ассемблера) - это прекрасный инструмент, позволяющий воочию и во всех тонкостях наблюдать процесс исполнения команд.
Начинающим осваивать ассемблер очень мешает отсутствие привычных чисел с плавающей запятой, символьных переменных и т. п. Тут уж ничего не поделаешь - процессор оперирует только с байтами и вариантов интерпретации их содержимого очень мало: целое число без знака (от О до 255) или со знаком (от -128 до 127). Впрочем, данные в виде пары байтов тоже иногда допустимы, но содержать они могут только целые числа без знака (от 0 до 65535). Все остальные виды данных приходится моделировать программисту.
Далее мы будем использовать следующие обозначения:
- R, R1, R2 - один из регистров А, В, С, D, Е, Н, L;
- RR, RR1, RR2 - одна из регистровых пар ВС, DE, HL или SP;
- N - 8-разрядное число от 0 до 255;
- NN - 16-разрядное число от 0 до 65535;
- М - ячейка памяти, адрес которой записан в регистровой паре HL;
- ( ) - содержимое ячейки памяти или регистра; например, (HL) - число, записанное в HL;
- [ ] - ячейка памяти с адресом, обозначенным в квадратных скобках; например, [(ВС)] - ячейка памяти, адрес которой равен числу, записанному в ВС;
- СС (от Cod Condition) - условие, которое должно быть проверено при выполнении команды.
Команд пересылки данных довольно много, они позволяют производить обмен данными между 8- и 16-разрядным и регистрами и ячейками памяти.
Ячейки памяти состоят из 8 битов, но благодаря специальным соглашениям в них можно хранить не только 8-разрядные числа. Если, например, нужно записать в ОЗУ двухбайтовое (16-разрядное) число, его заносят в две последовательно расположенные ячейки, причем младший байт числа (разряды 0-7) помещается в ячейку с меньшим адресом (некоторые типы процессоров имеют обратный порядок размещения байтов числа).
Командам пересылки данных все равно, что пересылать, для них важна только длина числа. В зависимости от типа команды перемещаются байт или два байта.
Для пересылки байта пользуются командами однобайтовых пересылок. Они могут занести константу в любой 8-разрядный (байтовый) регистр (непосредственная загрузка); скопировать содержимое любого байтового регистра в любой другой; переписать содержимое аккумулятора в память и загрузить аккумулятор из памяти, причем адрес в памяти может быть указан в команде числом (прямая адресация) или задаваться именем одной из регистровых пар ВС, DE или HL (косвенная адресация; в регистровой паре должен быть записан нужный адрес). Наконец, возможны непосредственный обмен данными между любым регистром и памятью и непосредственная загрузка константы в память (при этом адрес в памяти должен задаваться содержимым HL). Есть еще две команды ввода-вывода, которые тоже можно отнести к этой группе; одна записывает содержимое аккумулятора в порт (портами называют ячейки из адресного пространства ввода-вывода, чтобы подчеркнуть их отличие от ячеек памяти), другая загружает аккумулятор из порта. Номер порта (от 0 до 255) указывается непосредственно в команде.
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. Регистры здесь и далее кодируются следующим образом:
- А - 111
- В - 000
- С - 001
- D - 010
- Е - 011
- Н - 100
- L - 101
Таким образом, код, например, команды 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. Кроме того, появляются команды, не только пересылающие, но и обменивающие значения.
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 следующим образом:
- BC - 00
- DE - 01
- HL - 10
- PSW - 11
При выполнении этой команды происходят довольно сложные действия. Рассмотрим процесс выталкивания в стек содержимого HL (обратите внимание, что в мнемонику входит только имя старшего регистра):
PUSH H
Сначала содержимое регистра L помещается в ячейку памяти с адресом, равным содержимому регистра SP минус 2 (обозначим (SP)-2), а содержимое регистра Н - в ячейку с адресом (SP)-1; затем содержимое SP уменьшается на 2. Если в HL хранилось число 0102Н, а в SP - 9999Н, то после выполнения команды в ячейке 9998Н будет число 01Н, в ячейке 9997Н - число 02Н, а (SP) будет равно 9997Н; (SP) указывает на ячейку памяти с последним загруженным в стек числом.
Еще один пример. Пусть в аккумуляторе содержится число 55Н, в peгистре флагов - 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.
ПРОДОЛЖЕНИЕ СЛЕДУЕТ В ВЫПУСКЕ 05,06-1992