Программирование на БК-0010-01/Глава 4
Данный материал защищён авторскими правами!
Использование материала заявлено как добросовестное, исключительно для образовательных некоммерческих целей. |
Программирование в машинных кодах
4.1. Что понимается под программированием в кодах
Для чего нужно умение программировать в кодах ? Если Вы уже освоили с помощью предыдущих глав программирование на языке Бейсик, то, вероятно, можете сами ответить на этот вопрос. Основных причин может быть две. Во-первых, Бейсик не является чистым компилятором; создаваемый им шитый код выполняется в самом лучшем случае в несколько раз медленнее, чем аналогичная программа в машинных кодах. Если говорить о Фокале, то это чистый интерпретатор и работает еще медленнее.
Решение проблемы быстродействия очень просто: надо использовать не интерпретаторы, а компиляторы с языков высокого уровня. Компиляторами называются программы, сразу полностью переводящие программу в машинные коды. Полученную программу в машинных кодах можно сохранять и запускать сколько угодно раз. Только вот беда - ни один из компиляторов (например, с языков FORTRAN, PASCAL и т. п.) в БК не поместится. Для того, чтобы подготовить программу на этих языках для БК, нужно использовать инструментальную ЭВМ с большими возможностями (очень удобно это делать на ДВК в КУВТ). Но при отсутствии ДВК единственный выход — писать программы в кодах.
Вторая причина, по которой программирование в кодах на БК предпочтительнее, это ограниченный объем памяти БК. Чем плох Бейсик? Тем, что он хранит в памяти как сам исходный текст программы, так и полученный при его компиляции шитый код. Да еще нужно отвести место под данные программы. Если команда сложения на Бейсике «съедает» 52 байта (см. табл. 7), то в кодах она займет максимум 6 байт.
Итак, Ваш выбор - программирование в кодах. Несмотря на распространенность этого понятия, оно не совсем соответствует действительности. Непосредственно в кодах на БК практически никто не программирует. Обычно пользуются разными средствами облегчения этой работы — ассемблерами и отладчиками, котроые позволяют, как минимум, записывать машинные команды в удобной для человека форме (мнемонике).
Система МИКРО (А.Сомов, С.Шмытов, С.Кумандин, г. Москва) даже обеспечивает редактирование исходного текста и компиляцию программы на языке низкого уровня - ассемблере. Этот компилятор проще, чем компиляторы языков высокого уровня, и помещается в памяти БК, однако на текст программы и ее код остается мало места. Находящийся в ОЗУ текст программы можно странслировать, при этом получаем так называемый объектный модуль, который можно записать на магнитофон. Затем из небольших объектных модулей, загружаемых с магнитофона, собирается (компонуется) загрузочный модуль - собственно программа в кодах. Вынужденная работа мелкими кусочками, требующая частого использования магнитофона — плата за удобство программирования на ассемблере.
Наиболее удачным ассемблером-отладчиком для БК на сегодняшний день является система MIRAGE С.Зильберштейна (г. Киров). Здесь текст программы на ассемблере как таковой отсутствует. MIRAGE переводит коды, хранящиеся в ОЗУ с указанного адреса, в ассемблерную мнемонику (дизассемблирует). С помощью редактора в пределах одного экрана можно корректировать команды или добавлять новые, при этом они ассемблируются и записываются в виде машинных кодов в то же место ОЗУ. Такой способ работы имеет ряд недостатков — например, MIRAGE не может отличить данные от программы и также пытается их дизассемблировать. Но главное неудобство в том, что программисту все время приходится самому заботиться об адресах, и при встаке новой команды (или удалении) изменять адреса во всех командах перехода. Однако при определенной дисциплине и навыках работы это неудобство не смертельно. Зато в распоряжении программиста находится все ОЗУ в полном объеме, а магнитофон нужен только для периодического сохранения измененной программы. Плюс к тому MIRAGE позволяет отлаживать программу в кодах - запускать отдельные участки программы, прогонять ее по шагам с распечаткой текущих значений регистров процессора и т. п.
Только в том случае, когда у Вас не окажется ни одного из этих инструментов, программу можно писать непосредственно в кодах. Ввести ее в БК можно с помощью ТС-отладчика (см.п.2.5), либо с помощью Бейсика, как будет показано ниже. Еще одним способом улучшения качества программ может служить сочетание основной программы на Бейсике с подпрограммами в кодах. Об этом также будет рассказано ниже.
Рекомендуем после прочтения этой главы изучить следующую, взять имеющийся у Вас отладчик (п.п.5.1, 5.2) и с его помощью подробно изучить работу каждой команды обработки данных, описанной в данной главе. С помощью отладчиков Вы можете набирать короткие программы и, трассируя их, воочию увидеть, как работают те или иные команды, как при этом меняется содержимое регистров и как выставляются признаки в слове состояния процессора.
Рекомендуем также Вашему вниманию журнал «Информатика и образование», который в 1990 году начал публикацию цикла статей Ю.Зальцмана по архитектуре БК и программированию в кодах. В «Клубе пользователей БК», располагающемся в этом журнале, часто выступают известные программисты и любители БК, делящиеся полезными советами и разными тонкостями программирования.
4.2. Используемые в БК типы данных
Как Вы знаете, Бейсик позволяет работать с данными арифметического и текстового (строкового) типов, причем арифметические данные могут быть целого и вещественного (одинарной и двойной точности). Конечно, процессор БК не имеет таких широких возможностей. Например, обработка вещественных чисел может быть организована только программно, причем различные системы программирования (Бейсик, Фокал, PASCAL) могут использовать даже различные способы представления этих чисел). Основными данными, с которыми может работать процессор БК, являются байт и слово. Соответственно, в слове может быть размещено целое число, а в байте - один символ текста. В одном слове 16 бит - двоичных разрядов, поэтому из них можно 16 составить 2 = 65536 различных комбинаций. Если учесть, что машинные команды работы с целыми числами считают старший разряд (15-й бит) слова знаковым (0 - число положительное, 1 - число отрицательное), то диапазон целых чисел в БК будет от -32768 до +32767. Если в результате вычислений в Бейсике получится больший результат, он выдаст ошибку 6. Если то же самое произойдет в Вашей программе в кодах, никто этого не заметит, если не принять специальных мер. Тогда, прибавив единицу к числу 32767, Вы получите -32768. Для того, чтобы представить символы в памяти ЭВМ, их кодируют (см. 8 Приложение 1). В одном байте - 8 бит, что позволяет закодировать 2 = 256 различных символов. Этого вполне достаточно, чтобы разместить строчные и заглавные буквы двух алфавитов, цифры и другие спецзнаки. Именно для удобства кодировки символов и был выбран такой размер байта как единицы памяти ЭВМ. Следует также отметить, что для кодирования символов в БК использован советский стандарт КОИ - 8 бит, базирующийся на международном стандарте ASCII (American Standard Code for Information Interchange).
4.3. Программная модель процессора БК
Процессор ЭВМ - это сложная электронная схема. Однако знать все его особенности при программировании в кодах незачем. То, что нужно знать программисту о каком-либо устройстве ЭВМ, называется его программной моделью. Сюда относятся программно-доступные ячейки памяти устройства (их называют регистрами), а также алгоритм функционирования устройства. ┌─────────────────────────────────────────────────────────────────┐ │ П Р О Ц Е С С О Р │ │ │ │ 15 ... 7 6 5 4 3 2 1 0 │ │ ┌────────┬───┬───┬───┬───┬───┬───┬───┬───┐ │ │ Р С П │ │ P │ │ │ T │ N │ Z │ V │ C │ │ │ └────────┴───┴───┴───┴───┴───┴───┴───┴───┘ │ │ ┌────────────────────────────────────────┐ │ │ Р О Н : R0 │ │ │ │ ╞════════════════════════════════════════╡ │ │ R1 │ │ │ │ ╞════════════════════════════════════════╡ │ │ R2 │ │ │ │ ╞════════════════════════════════════════╡ │ │ R3 │ │ │ │ ╞════════════════════════════════════════╡ │ │ R4 │ │ │ │ ╞════════════════════════════════════════╡ │ │ R5 │ │ │ │ ╞════════════════════════════════════════╡ │ │ R6 │ SP │ │ │ ╞════════════════════════════════════════╡ │ │ R7 │ PC │ │ │ └────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘ Рис.11. Программная модель микропроцессора К1801ВМ1 Итак, используемый в БК микропроцессор К1801ВМ1 (рис.11) имеет 8 регистров общего назначения (РОН) и регистр слова состояния процессора (РСП). Все эти регистры 16-разрядные. Регистры общего назначения R0, R1, R2, R3, R4, R5 предназначены для хранения промежуточных результатов вычислений. Операции пересылки данных из одного регистра в другой выполняются гораздо быстрее, чем пересылка данных в ОЗУ. Оптимальное использование РОН в часто выполняемых циклах программы позволяет иногда ускорить ее на порядок. Регистр R6 обозначается в ассемблере "SP" (Stack Pointer - указатель стека) и используется в этом качестве как при вызове подпрограмм, так и при обработке прерываний. О нем будет подробно рассказано далее. Регистр R7 обозначается "PC" (Program Counter - счетчик команд) всегда содержит адрес следующей команды, котроую должен выполнить процессор. Рассмотрим подробнее алгоритм работы процессора, то есть опишем, как он выполняет программу. Программа должна начинать работу с определенного адреса памяти (с определенной команды). Для этого двоичный код адреса, с которого начинается программа, должен быть предварительно записан в регистр РС процессора (счетчик команд) - так как регистр РС всегда хранит адрес очередной команды, подлежащей выполнению. Допустим, в регистр РС записали восьмеричное число 7000 (все коды и адреса будем писать в восьмеричной системе счисления). Это значит, что следующей командой, исполняемой процессором, будет команда, хранящаяся по адресу 7000. Произойдет это так: из памяти с адреса 7000 в процессор перепишется слово - двоичный код команды для выполнения. Например, пусть по адресу 7000 была записана команда 60001. По этой команде процессор должен сложить содержимое R0 с содержимым R1. Причем результат сложения (сумма) запишется в R1. После выполнения процессором этой команды содержимое регистра РС автоматически увеличится на 2 (станет равным 7002). Теперь уже в процессор будет передана команда из ОЗУ с адреса 7002, и так далее. Действие команд перехода заключается в записи в регистр PC нового значения, и тогда процессор продолжит выполнять программу с указанного адреса. А что будет, если процессор в резултате ошибки программиста прочитает непонятную ему команду ? Ничего страшного, просто в этом случае выполнение программы будет прервано и процессор начнет выполнять программу из системного ПЗУ (как говорят, программа вылетит в МОНИТОР), либо управление возьмет на себя используемый отладчик (например, MIRAGE). Аналогичная ситуация возникнет, если в PC записать нечетное число (Вы помните, что длина команды кратна машинному слову, т.е. двум байтам, и ее адрес должен быть четным), либо такого адреса в микроЭВМ не существует. Остается только добавить, что после выполнения каждой команды программы меняется содержимое РСП. Этот регистр предназначен для хранения PSW (Processor Status Word - слово состояния процессора). В PSW имеют значение следующие биты (разряды): бит 0 (C) устанавливается в 1, если при выполнении команды произошел перенос единицы из старшего разряда результата; бит 1 (V) устанавливается в 1, если при выполнении арифметической команды (например, сложения) произошло арифметическое переполнение; бит 2 (Z) устанавливается в 1, если результат равен нулю; бит 3 (N) устанавливается в 1, если результат отрицателен. Эти биты PSW используются командами условного перехода. Остальные биты PSW устанавливаются программистом для задания режимов работы процессора: бит 4 (Т), установленный в 1, вызывает после выполнения очередной команды прерывание по вектору 14. Это используется программами - отладчиками для трассировки программы; бит 7 (P), установленный в 1, запрещает (маскирует) прерывания от внешних устройств (например, клавиатуры). Таким образом, командой установки PSW MTPS #200 можно запретить прерывания от клавиатуры до тех пор, пока не выполнится команда MTPS #0.
4.4. Система команд процессора БК
Процессор К1801ВМ1 "понимает" 64 разные команды. Все эти команды, вместе взятые, составляют систему команд процессора. Как уже говори- лось, система команд процессора БК практически совпадает с системой команд целой серии мини- и микроЭВМ (Электроника-60, ДВК, СМ). Команды процессора К1801ВМ1 условно можно разделить на 4 группы: однооперандные команды, двухоперандные команды, команды передачи управления и безоперандные команды. Двоичный код безоперандной команды содержит только код операции - информацию для процессора о том, что нужно делать по этой команде. Двоичный код однооперандной команды содержит код операции и информацию для процессора о местонахождении обрабатываемого числа (операнда), над которым нужно произвести операцию. Двухоперандные команды, помимо кода операции, содержат информацию для процессора о местонахождении 2-х чисел (операндов). Например, для сложения 2-х чисел команда должна содержать код операции сложения и информацию о том, откуда взять слагаемые. Далее коды команд процессора, а также коды операндов будем писать в восьмеричной системе счисления (как и коды адресов). Однако полезно помнить, что команды и операнды хранятся в памяти в двоичном коде - восьмеричный код мы будем использовать только для удобства. На рис.12 показано, как переводить 16-иразрядный двоичный код числа в восьмеричный код. 0 101 000 110 001 111 - двоичное число. └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ 0 5 0 6 1 7 - восьмеричное число. Рис.12. Перевод двоичного кода числа в восьмеричный Число 050617 в восьмеричной системе счисления получено из 16-иразрядного двоичного кода 0101000110001111 таким образом. Начиная с младшего разряда (справа) двоичное число делится на триады (группы по 3 цифры). Правда, старший разряд 16-разрядного числа при этом остается без "соседей". Затем для каждой триады записывается ее представление в восьмеричной системе счисления. В результате вместо 16-разрядного кода числа получаем 6-разрядный восьмеричный код. Разумеется, при написании программ удобнее работать с 6-разрядными кодами команд и чисел, чем с 16-разрядными - благо, все имеющиеся программы, облегчающие программирование в кодах, включая пультовый отладчик, понимают восьмеричную систему счисления.
4.4.1. Способы адресации операнда
В однооперандных командах процессора первые 4 восьмеричные цифры определяют код операции. Оставшиеся 2 цифры в коде команды процессор использует для определения местонахождения операнда, над которым нужно произвести операцию. Например, команда 005004 обнуляет регистр R4. Здесь первые 4 цифры кода команды "0050" являются кодом операции и указывают на то, что процессор должен произвести обнуление. Оставшиеся 2 цифры "04" указы- вают, что производится обнуление регистра R4. Нетрудно догадаться, что последняя цифра является номером того регистра, содержимое которого используется процессором при определении местонахождения операнда. Предпоследняя цифра (код способа адресации) указывает, каким образом содержимое регистра используется при определении местонахождения опе- ранда, то есть определяет способ адресации. В таблице 8 приведены способы адресации, использующие регистры общего назначения, кроме регистра РС. В первом столбце таблицы приведены названия, а во втором столбце - соответствующие восьмеричные коды способов адресации. В третьем столбце дается описание каждого способа адресации, а в четвертом столбце - соответствующие примеры на языке ассемблера. Таблица 8. Способы адресации через регистры R0-R6 ┌─────────────┬─────┬────────────────────────────┬──────────────┐ │ способ │ код │ описание способа │ примеры │ │ адресации │ │ адресации │ │ ╞═════════════╪═════╪════════════════════════════╪══════════════╡ │ регистровый │ 0 │ регистр содержит операнд │ CLR R1 │ ├─────────────┼─────┼────────────────────────────┼──────────────┤ │ косвенно - │ 1 │ регистр содержит адрес │ CLR (R1) │ │ регистровый │ │ операнда │ CLR @R1 │ ├─────────────┼─────┼────────────────────────────┼──────────────┤ │ автоинкре- │ 2 │ регистр содержит адрес опе-│ CLR (R2)+ │ │ ментный │ │ ранда. Содержимое регистра │ │ │ │ │ после его использования в │ │ │ │ │ качестве адреса увеличива- │ │ │ │ │ ется на 2 (для команд над │ │ │ │ │ словами) или на 1 (для │ │ │ │ │ байтовых команд) │ │ ├─────────────┼─────┼────────────────────────────┼──────────────┤ │ косвенно - │ 3 │ регистр содержит адрес │ CLR @(R2)+ │ │ автоинкре- │ │ адреса операнда. Содер- │ │ │ ментный │ │ жимое регистра после его │ │ │ │ │ использования в качестве │ │ │ │ │ адреса увеличивается на 2 │ │ ├─────────────┼─────┼────────────────────────────┼──────────────┤ │ автодекре- │ 4 │ содержимое регистра умень- │ CLR -(R2) │ │ ментный │ │ шается на 2 ( для команд │ │ │ │ │ над словами ) или на 1(для │ │ │ │ │ байтовых команд ) и исполь-│ │ │ │ │ зуется как адрес операнда │ │ ├─────────────┼─────┼────────────────────────────┼──────────────┤ │ косвенно - │ 5 │ содержимое регистра умень- │ CLR @-(R1) │ │ автодекре- │ │ шается на 2 и используется │ │ │ ментный │ │ как адрес адреса операнда. │ │ ├─────────────┼─────┼────────────────────────────┼──────────────┤ │ индексный │ 6 │ содержимое регистра скла- │ CLR 2(R5) │ │ │ │ дывается с числом, записан-│ CLR MT(R0) │ │ │ │ ным после команды, и полу- │ │ │ │ │ ченная сумма используется │ │ │ │ │ в качестве адреса операнда │ │ ├─────────────┼─────┼────────────────────────────┼──────────────┤ │ косвенно - │ 7 │ содержимое регистра склады-│ CLR @22(R1) │ │ индексный │ │ вается с числом, записанным│ │ │ │ │ после команды и полученная │ │ │ │ │ сумма используется в качес-│ │ │ │ │ тве адреса адреса операнда │ │ └─────────────┴─────┴────────────────────────────┴──────────────┘ В команде 005004, например, применен регистровый способ адресации, использующий регистр R4. Если адресация операнда происходит через регистр РС, то способы адресации другие (таблица 9). Таблица 9. Способы адресации через регистр РС ┌─────────────┬─────┬────────────────────────────┬──────────────┐ │ способ │ код │ описание способа │ примеры │ │ адресации │ │ адресации │ │ ╞═════════════╪═════╪════════════════════════════╪══════════════╡ │ непосред- │ 2 │ операнд хранится в слове, │ MOV #21,R3 │ │ ственный │ │ следующем за командой │ MOV #IN,R0 │ │ │ │ за командой. │ │ ├─────────────┼─────┼────────────────────────────┼──────────────┤ │ абсолютный │ 3 │ адрес операнда хранится в │ CLR @#7000 │ │ │ │слове, следующем за командой│ JMP @#BEN │ ├─────────────┼─────┼────────────────────────────┼──────────────┤ │ относитель- │ 6 │ содержимое РС складывается │ JMP TV │ │ ный │ │ со словом, записанным в │ CLR 5554 │ │ │ │ памяти за командой, и по- │ │ │ │ │ лученная сумма используется│ │ │ │ │ как адрес операнда. │ │ ├─────────────┼─────┼────────────────────────────┼──────────────┤ │ косвенно - │ 7 │ содержимое РС складывается │ CLR @MET │ │ относитель- │ │ со словом, следующим за │ INC @15342 │ │ ный │ │ командой, полученная сумма │ │ │ │ │ используется как адрес │ │ │ │ │ адреса операнда. │ │ └─────────────┴─────┴────────────────────────────┴──────────────┘
4.4.2. Однооперандные команды
Перейдем к рассмотрению однооперандных команд. Одна из них, команда обнуления регистра процессора или ячейки памяти, нам уже знакома: 0050DD Так как для каждого конкретного способа адресации последние две цифры в коде однооперандной команды будут разными (какими - зависит от программиста), то здесь и далее при написании кода какой-либо однооперандной команды вместо последних 2-х цифр будем писать "DD". Ту часть кода команды, которая обозначена двумя буквами "DD", будем называть полем адресации операнда (рис.13). 0 0 5 0 D D └──┬──┘ └┬┘ код операции поле адресации Рис.13. Пример однооперандной команды То, что команда имеет один операнд, еще ничего не говорит о длине команды. Это зависит от способа адресации операнда. Если способ адресации регистровый, то команда занимает одно слово, если индексный либо с использованием PC - два слова (во втором слове помещается операнд, его адрес либо индекс. В таблице 10 приводится описание однооперандных команд. Таблица требует пояснений. Некоторые команды могут обрабатывать как целые слова, так и байты. В таблице вместо первой цифры кода каждой такой команды стоит символ "*". В том случае, если команда предназначена для работы с байтом, то в ее коде первой цифрой ставится "1", а иначе - "0". Если в качестве операнда байтовой команды служит один из регистров общего назначения процессора, то имеется в виду его младший байт. Каждая команда системы команд, помимо своего числового кода, имеет свою мнемонику (мнемокод) - обозначение в виде последовательности нескольких латинских букв, что используется при программировании на языке ассемблера. Например, мнемокод команды обнуления содержимого какого-либо регистра (или слова памяти) состоит из трех букв: CLR (от английского слова Clear - очистить). Команда, предназначенная для обработки байта (байтовая команда), имеет такой же мнемокод, что и соответствующая команда для обработки слова, но к мнемокоду справа добавляется буква "В". Например, команда, предназначенная для очистки отдельного байта, имеет мнемокод: CLRB (от английского Clear Byte - очистить байт ). Для команд, которые могут обрабатывать как слова, так и байты, в таблице в скобках указан возможный суффикс "B". Таблица 10. Основные однооперандные команды ┌──────────┬──────────┬─────────────────────────────────┐ │ код │ мнемокод │ действие команды │ │ команды │ команды │ │ ╞══════════╪══════════╪═════════════════════════════════╡ │ *050DD │ CLR(B) │ Clear - очистить │ ├──────────┼──────────┼─────────────────────────────────┤ │ *051DD │ COM(B) │ Complement - инвертировать │ ├──────────┼──────────┼─────────────────────────────────┤ │ *052DD │ INC(B) │ Increment - увеличить │ ├──────────┼──────────┼─────────────────────────────────┤ │ *053DD │ DEC(B) │ Decrement - уменьшить │ ├──────────┼──────────┼─────────────────────────────────┤ │ *054DD │ NEG(B) │ Negate - изменить знак │ ├──────────┼──────────┼─────────────────────────────────┤ │ *055DD │ ADC(B) │ Add Carry - сложить с переносом │ ├──────────┼──────────┼─────────────────────────────────┤ │ *056DD │ SBC(B) │ Subtract Carry -вычесть перенос │ ├──────────┼──────────┼─────────────────────────────────┤ │ *057DD │ TST(B) │ Test - тестировать, проверить │ ├──────────┼──────────┼─────────────────────────────────┤ │ *060DD │ ROR(B) │ Rotate Right - циклически сдви- │ │ │ │ нуть вправо │ ├──────────┼──────────┼─────────────────────────────────┤ │ *061DD │ ROL(B) │ Rotate Left - циклически сдви- │ │ │ │ нуть влево │ ├──────────┼──────────┼─────────────────────────────────┤ │ *062DD │ ASR(B) │ Arithmetic Shift Right - │ │ │ │ арифметически сдвинуть вправо │ ├──────────┼──────────┼─────────────────────────────────┤ │ *063DD │ ASL(B) │ Arithmetic Shift Left - │ │ │ │ арифметически сдвинуть влево │ ├──────────┼──────────┼─────────────────────────────────┤ │ 0003DD │ SWAB │ Swap Bytes - переставить байты │ ├──────────┼──────────┼─────────────────────────────────┤ │ 1064DD │ MTPS │ Move To PSW( Processor Status │ │ │ │ Word) - записать слово │ │ │ │ состояния процессора ) │ ├──────────┼──────────┼─────────────────────────────────┤ │ 1067DD │ MFPS │ Move From PSW - прочитать PSW │ └──────────┴──────────┴─────────────────────────────────┘ Рассмотрим подробнее каждую команду процессора (для определенности будем иметь в виду команды, обрабатывающие слово памяти или содержимое регистра процессора, поэтому далее при написании кода команды вместо символа "*" будем проставлять цифру "0"). Первая команда (CLR) нам уже знакома - перейдем к рассмотрению остальных команд.
Команда 0051DD. Мнемокод: COM
По этой команде образуется инверсный (обратный) код операнда - во всех разрядах операнда нули заменяются единицами, а единицы - нулями. Это действие представляет собой логическую операцию отрицания ("НЕ"). Пример: 005121 COM (R1)+ Команда образует инверсный код слова, адрес которого хранится в регистре R1, после чего содержимое регистра R1 увеличивается на 2. Далее в примерах справа от каждой команды будем писать соответствующую ассемблерную мнемонику.
Команда 0052DD. Мнемокод: INC
Увеличивает значение операнда на 1. Пример: 005237 INC @#10000 010000 Команда 005237 увеличивает на 1 содержимое слова памяти с адресом 10000 - на 1 увеличивается число, хранящееся в 2-х ячейках с адресами 10000 и 10001. Две последние цифры "37" в коде команды указывают, что адрес операнда хранится в памяти за кодом команды (абсолютная адресация). Значение адреса 10000 в примере записано под кодом команды 005237 (в один столбец). Такая запись означает, что начиная с определенного адреса (например, с адреса 7000) в памяти записан код команды 005237 (два байта), затем (по адресу 7002) записано число 10000.
Команда 0053DD. Мнемокод: DEC
Уменьшает значение операнда на 1. Пример: 005312 DEC (R2) Команда уменьшает на 1 слово, адрес которого хранится в регистре R2.
Команда 0054DD. Мнемокод: NEG
Изменяет знак операнда. Пример: 005412 NEG @R2 Команда изменяет знак числа, хранящегося по адресу, указанному в R2. Если число было положительным, то станет отрицательным, и наоборот. Операция изменения знака числа в процессоре БК эквивалентна получению дополнительного кода числа (то есть числа, которое, будучи сложено с исходным, даст в сумме ноль). Формирование дополнительного двоичного кода числа состоит из двух последовательных операций : получения инверсного (обратного) двоичного кода числа и прибавления 1 (к полученному инверсному коду). Пример: 01001011 - двоичный код операнда (байта) 10110101 - дополнительный двоичный код операнда Отметим также, что в двух предыдущих примерах обозначения "(R2)" и "@R2" равнозначны.
Команда 0055DD. Мнемокод: ADC
Увеличивает значение операнда на содержимое разряда С PSW.
Команда 0056DD. Мнемокод: SBC
Уменьшает значение операнда на содержимое разряда С PSW.
Команда 0057DD. Мнемокод: TST
По этой команде производится тестирование (проверка) значения операнда и установка в "1" (или сброс в "0") разрядов Z и N PSW, а разряды V и C при этом сбрасываются в "0". Если значение операнда отрицательно, то разряд N PSW установится в "1", иначе сбросится в "0". Если значение операнда нулевое, то разряд Z установится в "1", иначе сбросится в "0". Значение операнда при этом не изменяется.
Команда 0060DD. Мнемокод: ROR
Производит циклический сдвиг значений разрядов операнда вправо на один разряд (рис.14). Значение 15-го разряда загружается в 14-ый разряд, значение 14-го разряда - в 13-ый разряд и так далее. Значение разряда С PSW загружается в 15-ый разряд операнда, а значение нулевого (младшего) разряда операнда - в разряд С PSW. разряд С PSW 15 операнд 0 ┌───┐ ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ ┌─────│ С ├─────│ ├────┐ │ └───┘ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ │ └──────────────────────────────────────────────────────┘ Рис.14. Циклический сдвиг вправо
Команда 0061DD. Мнемокод: ROL
Команда выполняется так же, как и предыдущая, но сдвиг выполняется влево и значение разряда С PSW загружается в нулевой разряд операнда, а значение 15-ого разряда операнда - в разряд С PSW.
Команда 0062DD. Мнемокод: ASR
Производит арифметический сдвиг вправо. При этом значение каждого разряда операнда сдвигается на один разряд вправо. Значение нулевого разряда операнда загружается в разряд С PSW. В 14-ый и 15-ый разряды записывается значение 15-ого разряда операнда (рис.15). 15 операнд 0 разряд С PSW ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ ┌───┐ │ ├───>│ С │ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ └───┘ Рис.15. Арифметический сдвиг вправо
Команда 0063DD. Мнемокод: ASL
Производит арифметический сдвиг значения каждого разряда операнда на один разряд влево. Нулевой разряд операнда очищается, а значение 15-ого разряда операнда загружается в разряд С PSW (рис.16). разряд С PSW 15 операнд 0 ┌───┐ ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ ┌───┐ │ С │<────┤ │<───┤ 0 │ └───┘ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ └───┘ Рис.16. Арифметический сдвиг влево Арифметический сдвиг влево равносилен умножению операнда на 2, а арифметический сдвиг вправо - делению операнда на 2.
Команда 0003DD. Мнемокод: SWAB
Меняет местами старший и младший байты операнда (слова).
Команда 1064DD. Мнемокод: MTPS
Команда записывает в РСП новое значение слова состояния процессора (PSW), равное значению операнда. Пример: 106427 MTPS #200 000200 В данном примере в РСП загружается новое значение PSW, равное 200. Таким образом, устанавливается в 1 бит приоритета "P" в PSW, что запрещает процессору обрабатывать прерывания от клавиатуры до тех пор, пока не будет выполнена команда MTPS #0.
Команда 1067DD. Мнемокод: MFPS
Команда пересылает PSW в место, определяемое полем адресации операнда. Пример: 106702 MFPS R2 Производится пересылка PSW в регистр R2.
4.4.3. Двухоперандные команды
Код двухоперандной команды, кроме кода операции, должен содержать 2 поля адресации операнда. Первое поле адресации операнда, обозначаемое в коде команды двумя буквами "SS", определяет местонахождение 1-ого операнда команды и называется полем адресации операнда источника. Второе поле адресации операнда, обозначаемое в коде команды буквами "DD", определяет местонахождение 2-ого операнда команды и называется полем адресации операнда приемника (рис.17). Первый операнд команды называется операндом источника, второй операнд - операндом приемника. Смысл обозначений "SS" и "DD" такой же, что и для обозначения "DD" в коде однооперандной команды. Основные двухоперандные команды , рассматриваемые здесь, приведены в таблице 11.
Команда 01SSDD. Мнемокод: MOV
По этой команде операнд, местонахождение которого определяется полем адресации "SS", пересылается по адресу, определяемому полем адресации "DD". При этом содержимое источника, откуда берется операнд для пересылки, не изменяется. При выполнении байтовой команды MOVB с использованием регистрового способа адресации (для операнда приемника) все разряды старшего байта операнда приемника устанавливаются в "1", если знаковый разряд (старший разряд) младшего байта установлен в "1", иначе разряды старшего байта сбрасываются в "0". Пример: 010204 MOV R2,R4 Копия содержимого регистра R2 пересылается (загружается) в регистр R4. Содержимое R2 при этом не изменяется. Более сложный пример: Команда Текст на ассемблере 012737 MOV #177777,@#70000 177777 070000 0 1 S S D D └┬┘ └┬┘ └┬┘ ┌────────┘ │ └─────────────┐ код поле адресации поле адресации операции операнда операнда источника приемника Рис.17. Пример двухоперандной команды Таблица 11. Двухоперандные команды ┌──────────┬──────────┬─────────────────────────────────┐ │ код │ мнемокод │ действие команды │ │ команды │ команды │ │ ╞══════════╪══════════╪═════════════════════════════════╡ │ *1SSDD │ MOV(B) │ Move - переслать │ ├──────────┼──────────┼─────────────────────────────────┤ │ *2SSDD │ CMP(B) │ Compare - сравнить │ ├──────────┼──────────┼─────────────────────────────────┤ │ *3SSDD │ BIT(B) │ Bit Test - тестировать биты │ ├──────────┼──────────┼─────────────────────────────────┤ │ *4SSDD │ BIC(B) │ Bit Clear - очистить биты │ ├──────────┼──────────┼─────────────────────────────────┤ │ *5SSDD │ BIS(B) │ Bit Set - установить биты │ ├──────────┼──────────┼─────────────────────────────────┤ │ 06SSDD │ ADD │ Add - сложить │ ├──────────┼──────────┼─────────────────────────────────┤ │ 16SSDD │ SUB │ Subtract - вычесть │ ├──────────┼──────────┼─────────────────────────────────┤ │ 074RDD │ XOR │ логическая операция XOR (исклю- │ │ │ │ чающее ИЛИ) над регистром R и │ │ │ │ приемником DD │ └──────────┴──────────┴─────────────────────────────────┘ Здесь одна команда занимает 3 слова памяти. В 1-ом слове записан код самой команды - число 012737. Во 2-ом слове хранится операнд источника ( число 177777 ), предназначенный для пересылки, и в 3-ем слове хранится адрес приемника 70000, куда пересылается число 177777. Две цифры "27" в коде команды, записанные в поле адресации операнда источника, указывают, что операнд источника (число 177777) хранится в памяти сразу же за кодом команды. Две цифры "37", записанные в поле адресации операнда приемника указывают, что значение адреса приемника хранится в памяти также за кодом команды - но в данном случае место в памяти сразу же за кодом команды занято числом 177777, поэтому значение адреса приемника (число 70000) записывается в памяти за числом 177777.
Команда 02SSDD. Мнемокод: CMP
Данная команда вычитает из операнда источника операнд приемника. Но при этом значения самих операндов не изменяются. Изменяются лишь значения разрядов C,V,Z,N PSW. Разряд N устанавливается в "1", если результат вычитания - отрицательное число. Разряд Z устанавливается в "1", если результат - равен нулю (операнды равны). Разряд V устанавливается в "1", если было арифметическое переполнение - если операнды были противоположного знака, а знак результата совпадает со знаком операнда приемника. Разряд С обнуляется, если был перенос из старшего разряда результата вычитания. Пример: 020103 CMP R1,R3 Команда 020103 производит сравнение содержимого регистра R1 с содержимым регистра R3.
Команда 03SSDD. Мнемокод: BIT
Значение каждого разряда результата образуется логическим умножением значений соответствующего разряда операнда источника и операнда приемника. Например, значение 12-ого разряда результата образуется логическим умножением значений 12-ого разряда операнда источника и 12-ого разряда операнда приемника. В таблице 12 показано, чему равен результат логического умножения (операции "И") при разных комбинациях значений какого-либо разряда операнда источника и операнда приемника. Значения операнда источника и операнда приемника при выполнении команды не изменяются. Изменяются лишь значения разрядов V,Z,N PSW. Разряд N устанавливается в "1", если в результате поразрядного логического умножения 2-х операндов получилось число, знаковый (старший) разряд которого установлен в "1". Разряд Z устанавливается в "1", если в результате логического умножения получилось число, все разряды которого сброшены в "0". Разряд V PSW сбрасывается в "0". Данная команда используется для проверки состояния (значения) отдельных разрядов одного из операндов. Пример: Команда Текст программы на ассемблере 032737 BIT #100,@#177716 ;нажата ли клавиша ? 000100 177716 0014.. BEQ MET ;переход к обработке нажатой клавиши Таблица 12. Логические операции ┌───────────────────────────────────────────────────┬───┬───┬───┬───┐ │ значение разряда операнда источника │ 0 │ 0 │ 1 │ 1 │ ├───────────────────────────────────────────────────┼───┼───┼───┼───┤ │ значение разряда операнда приемника │ 0 │ 1 │ 0 │ 1 │ ╞═══════════════════════════════════════════════════╪═══╪═══╪═══╪═══╡ │ результат логического умножения (операции "И") │ 0 │ 0 │ 0 │ 1 │ ├───────────────────────────────────────────────────┼───┼───┼───┼───┤ │ результат логического сложения (операции "ИЛИ") │ 0 │ 1 │ 1 │ 1 │ ├───────────────────────────────────────────────────┼───┼───┼───┼───┤ │ результат операции "исключающее ИЛИ" (XOR) │ 0 │ 1 │ 1 │ 0 │ └───────────────────────────────────────────────────┴───┴───┴───┴───┘
Команда 04SSDD. Мнемокод: BIC
По этой команде сбрасываются в "0" (обнуляются) разряды операнда приемника, соответствующие установленным в "1" разрядам операнда источника. Остальные разряды операнда приемника остаются без изменений. Значение операнда источника при выполнении команды не изменяется. Действие этой команды эквивалентно выполнению последовательности логических операций: инвертирования (отрицание) операнда источника; логического умножения ("И") результата и операнда приемника; запись результата в операнд приемника. Пример: 1111111100000000 <───- двоичный код операнда источника 1010011110001010 <──── двоичный код операнда приемника до выполнения команды 0000000010001010 <──── двоичный код операнда приемника после выполнения команды
Команда 05SSDD. Мнемокод: BIS
По этой команде устанавливаются в "1" разряды операнда приемника, соответствующие установленным в "1" разрядам операнда источника. Остальные разряды операнда приемника остаются без изменений. Значение операнда источника при выполнении команды не меняется. Действие этой команды эквивалентно операции логического сложения ("ИЛИ") над операндами источника и приемника (см. табл. 12). Пример: 1111111100000000 <──── двоичный код операнда источника 1010011110001010 <───- двоичный код операнда приемника до выполнения команды 1111111110001010 <──── двоичный код операнда приемника после выполнеия команды При выполнении команд BIC и BIS значения разрядов V,Z,N PSW изменяются в зависимости от значения результата так же, как при выполнении команды BIT.
Команда 06SSDD. Мнемокод: ADD
Команда суммирует операнд источника с операндом приемника. Результат сложения записывается по адресу операнда приемника. Значение операнда источника при этом не изменяется. Значение разрядов Z и N PSW изменяются так же, как и для команды СМР. Разряд V PSW устанавливается в "1", если в результате выполнения команды произошло арифметическое переполнение, то есть, если оба операнда были одного знака, а результат сложения получился противоположного знака. В обычной арифметике такого не бывает, а в работе процессора такой парадокс возможен в силу того, что разрядность процессора ограничена. Разряд С PSW устанавливается в "1", если был перенос из старшего разряда результата. Пример: 060204 ADD R2,R4 Производится сложение содержимого 2-х регистров: R2 и R4. Результат сложения помещается в регистр R4.
Команда 16SSDD. Мнемокод: SUB
По этой команде из операнда приемника вычитается операнд источника. Результат помещается по адресу операнда приемника. Изменение разрядов C,Z,N PSW происходит так же, как при выполнении команды СМР. Арифметическое переполнение при выполнении данной команды происходит, когда операнды имели разные знаки, а знак результата совпадает со знаком операнда источника. Пример: Адрес Команда Текст программы на ассемблере 20000: 166767 SUB VR1,S 20002: 000004 20004: 000006 20006: 000207 RTS PC 20010: 000056 VR1: .#56 20012: 000012 VR2: .#12 20014: 000010 S: .#10 Здесь и далее в примерах по необходимости слева от каждой команды (или операнда) будем писать соответствующий адрес. В приведенном фрагменте программы команда SUB, хранящаяся по адресу 20000, производит вычитание значения переменной VR1 из значения переменной S. Результат вычитания присваивается переменной S. По адресу 20002 хранится смещение для определения адреса операнда источника (значения переменной VR1), а по адресу 20004 - смещение для определения адреса операнда приемника (значения переменной S). Для определения адреса операнда источника процессор складывает смещение, хранящееся по адресу 20002, с содержимым регистра РС. После пересылки указанного значения смещения в процессор содержимое регистра РС равно 20004 - поэтому искомое значение адреса операнда источника равно смещение + РС = 4 + 20004 = 20010 . Аналогично определяется адрес операнда приемника: смещение + РС = 6 + 20006 = 20014 .
4.4.4. Команды передачи управления
4.4.4.1. Команды перехода
Каждая команда перехода занимает одно слово памяти (кроме команды JMP) и имеет формат, изображенный на рисунке 18. 15 8 7 0 ┌─────────────────────────┬───────────────────────┐ │ код операции │ смещение │ └─────────────────────────┴───────────────────────┘ Рис.18. Формат команды перехода Команды JMP и SOB имеют другой формат и поэтому будут рассмотрены позже отдельно. Команда перехода (ветвления) позволяет изменить содержимое счетчика команд (регистра PC) на величину смещения, указанного в младшем байте кода команды. А изменение содержимого счетчика команд на величину смещения приведет к продолжению выполнения программы с адреса, равного выражению: АП = АК + 2 + 2 * СМ где АП - адрес, с которого продолжится выполнение программы после исполнения команды перехода (адрес перехода); АК - адрес, где хранится сама команда перехода; СМ - смещение, указанное в коде команды перехода. Старший разряд смещения (разряд 7 в коде команды) является знаковым и равен "1" (для отрицательных смещений) или "0" (для положительных смещений). Так как для хранения значения смещения отводится только младший байт кода команды, то оно не может выйти за границы интервала от -128Д до +127Д.
Команда 000400. Мнемокод: BR
Действия процессора по команде BR соответствуют действию оператора GOTO в программе на языке Бейсик. Если оператор GOTO передает управление на определенную строку программы на Бейсике, то команда BR- на определенный адрес памяти (адрес перехода), начиная с которого будет продолжено выполнение программы. По команде BR произойдет безусловный переход на адрес перехода - процессор продолжит выполнение программы с адреса перехода . Код команды BR равен 000400 только в том случае, если смещение равно 0. Кстати, в каждой команде, приведенной в таблице 13, значение смещения равно 0 (кроме команды JMP). Полный код команды определяется Таблица 13. Команды перехода ┌──────────┬──────────┬─────────────────────────────────────────┐ │ код │ мнемокод │ действие команды │ │ команды │ команды │ │ ╞══════════╪══════════╪═════════════════════════════════════════╡ │ 000400 │ BR │ Branch - переход │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 001000 │ BNE │ Branch if Not Equal - переход, если │ │ │ │ не равно │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 001400 │ BEQ │ Branch if Equal - переход, если равно │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 100000 │ BPL │ Branch if Plus - переход, если плюс │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 100400 │ BMI │ Branch if Minus - переход, если минус │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 102000 │ BVC │ Branch if V is Clear - переход, если │ │ │ │ разряд V PSW очишен (сброшен в "0") │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 102400 │ BVS │ Branch if V is Set - переход, если │ │ │ │ разряд V PSW установлен в "1" │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 002000 │ BGE │ Branch if Greater or Equal - переход, │ │ │ │ если больше или равно │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 002400 │ BLT │ Branch if Less Then - переход, если │ │ │ │ меньше чем │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 003000 │ BGT │ Branch if Greater Then - переход, если │ │ │ │ больше чем │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 003400 │ BLE │ Branch if Less or Equal - переход, │ │ │ │ если меньше или равно │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 101000 │ BHI │ Branch if Higher - переход, если выше │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 101400 │ BLOS │ Branch if Lower or Same - переход, │ │ │ │ если ниже или столько же │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 103000 │ BHIS(BCC)│ Branch if Higher or Same - переход, │ │ │ │ если выше или столько же (или бит C PSW │ │ │ │ равен 0) │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 103400 │ BLO(BCS) │ Branch if Lower - переход, если ниже │ │ │ │ (или бит C PSW равен 1) │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 077R00 │ SOB │ Subtract One and Branch, if not equal - │ │ │ │ вычесть 1 и сделать переход, если не 0 │ ├──────────┼──────────┼─────────────────────────────────────────┤ │ 0001DD │ JMP │ Jump - прыгнуть (перейти) │ └──────────┴──────────┴─────────────────────────────────────────┘ сложением кода команды, указанного в таблице 13, и значения смещения, которое равно выражению CM = (АП - АК - 2) / 2 . Пример: Адрес Команда Текст программы на ассемблере 7000: 000401 BR TT 7002: 005001 CLR R1 7004: 010102 TT: MOV R1,R2 В данном примере первая команда производит переход на адрес 7004. Значение смещения определилось так: СМ=(АП-АК-2)/2=(7004-7000-2)/2=1 . Во фрагменте программы на языке ассемблера использована метка ТТ, обозначающая адрес памяти, где размещена команда MOV R1,R2. Команда BR TT передает управление на адрес, обозначенный ("помеченный") меткой TТ. Имена всех меток на языке ассемблера заканчиваются символом ":". Рассмотрим следующий пример, когда значение смещения - отрицатель- ное число (переход производится в сторону младших адресов): Адрес Команда Текст программы на ассемблере 35004: 005001 V0: CLR R1 ... ... ... 35036: 000762 BR V0 Команда 000762 производит переход на адрес 35004. Значение смещения определяется так: СМ=(АП-АК-2)/2=(35004-35036-2)/2=-34/2. Значение смещения - отрицательное число, поэтому оно должно быть представлено в дополнительном коде. Для расчетов удобно использовать Бейсик: PRINT OCT$(-&O34/2) . На экран выводится восьмеричное число 177762. Так как смещение занимает только младший байт кода команды, то искомое значение смещения равно выражению: 177762-177400=362. Тогда полный код команды равен 000762 (сумме кода команды 000400 и смещения 362).
Команда 001000. Мнемокод: BNE
По команде BNE переход произойдет, если разряд Z PSW сброшен в "0". Пример: Адрес Команда Текст программы на ассемблере 1000: 020104 CMP R1,R4 1002: 001001 BNE MET 1004: 010102 MOV R1,R2 1006: 010103 MET: MOV R1,R3 В этом примере первая команда сравнивает содержимое регистра R1 с содержимым регистра R4. В результате такого сравнения разряд Z PSW установится в "1" (если содержимые регистров R1 и R4 равны) или сбросится в "0" (если содержимые регистров не равны). Если содержимые регистров не равны (если разряд Z PSW сброшен в "0"), то вторая команда 001001 передает управление на адрес, где хранится 4-ая команда 010103, минуя 3-ю команду 010102. В противном случае (если разряд Z PSW установлен в "1") естественный порядок выполнения программы не нарушается - все 4 команды выполняются одна за другой.
Команда 001400. Мнемокод: BEQ
Команда BEQ является обратной по отношению к команде BNE. Переход по этой команде произойдет, если разряд Z PSW установлен в "1".
Команда 100000. Мнемокод: BPL
По команде BPL произойдет переход, если разряд N PSW сброшен в "0". Пример: Адрес Команда Текст программы на ассемблере 1000: 005710 TST (R0) 1002: 100002 BPL PL 1004: 005210 INC (R0) 1006: 004001 BR MIN 1010: 005310 PL: DEC (R0) 1012: 011002 MIN: MOV (R0),R2 Команда 005710 (TST) тестирует (проверяет) содержимое слова памяти, адрес которого хранится в R0. По команде 100002 произойдет переход, если при выполнении предыдущей команды (TST) разряд N PSW был сброшен в "0" (это произойдет, если тестируемый операнд больше или равен 0).
Команда 100400. Мнемокод: BMI
Команда является обратной по отношению к команде BPL. По команде BMI переход произойдет, если к моменту выполнения команды BMI разряд N PSW установлен в "1".
Команда 102000. Мнемокод: BVC
Переход по этой команде произойдет, если разряд V PSW сброшен в "0".
Команда 102400. Мнемокод: BVS
Переход по этой команде произойдет, если разряд V PSW установлен в "1".
Команда 002000. Мнемокод: BGE
Рассмотрим пример: Адрес Команда Текст программы на ассемблере 5000: 010103 MOV R1,R3 5002: 020102 CMP R1,R2 5004: 002001 BGE M1 5006: 010203 MOV R2,R3 5010: ... M1: ... Команда 020102 (CМР) сравнивает содержимое регистров R1 и R2. По команде 002001 (BGE) произойдет переход, если содержимое регистра R1 оказалось больше или равно содержимому R2. Нетрудно догадаться, что в результате выполнения данной программы в R3 будет находиться максимальное значение из содержащихся в R1 и R2.
Команда 002400. Мнемокод: BLT
Если в предыдущем примере вместо команды BGE поставить команду BLT, то переход по команде BLT произойдет, если содержимое R1 окажется меньше содержимого R2, и в результате программа получит в R3 минимальное значение.
Команда 003000. Мнемокод: BGT
Если команда BGT следует за командой сравнения двух операндов, то переход произойдет, если операнд источника больше операнда приемника.
Команда 003400. Мнемокод: BLE
Если команда BLE следует за командой сравнения двух операндов, то переход произойдет, если операнд источника меньше или равен операнду приемника. Команды BGE, BLT, BGT и BLE можно использовать для перехода после сравнения двух операндов, как чисел со знаком. Команды BHI, BLOS, BHIS и BLO, приведенные в таблице 13, также можно использовать для перехода после сравнения двух операндов. Но в этом случае операнды рассматриваются не как числа со знаком, а как 16-разрядные целые числа без знака в диапазоне от 0 до 65535. Таким способом имеет смысл сравнивать адреса. Ниже приведены соответствия между этими командами: BGE - BHIS BGT - BHI BLT - BLO BLE - BLOS
Команда 077R00. Мнемокод: SOB
Формат команды SOB изображен на рисунке 19. 15 9 8 6 5 0 ┌──────────────────────┬─────────┬────────────┐ │ код операции ( 077 ) │ регистр │ смещение │ └──────────────────────┴─────────┴────────────┘ Рис.19. Формат команды SOB Значение смещения занимает 6 младших разрядов кода команды и рассматривается как число без знака - так как переход по этой команде происходит только в обратном направлении (в сторону уменьшения адресов). Причем переход произойдет только в том случае, если содержимое регистра, указанного в коде команды, после вычитания из него 1 не равно 0. В коде команды 077R00 вместо буквы "R" указывается номер регистра, участвующего в операции. Код команды SOB равен 077R00 только в том случае, если значение смещения равно 0. Для получения кода команды со смещением, отличным от 0, к коду команды 077R00 прибавляется значение смещения , равное значению выражения ( АК + 2 - АП ) / 2 где АК - адрес команды SOB; АП - адрес перехода. Значения адресов АК и АП задаются в восьмеричной системе счисления- поэтому все расчеты в указанном выражении ведутся по восьмеричной системе счисления. Например, (1036+2-1034)/2=2; (1056+2-1002)/2=27. Расчеты значения смещения по данной формуле можно производить, используя десятичные значения адресов АК и АП - но результат после этого должен быть представлен в восьмеричной системе счисления. Например, код команды без смещения равен 077300 и восьмеричное значение смещения равно 27, тогда код команды, содержащий необходимое значение смещения, будет равен 077327. Пример: Адрес Команда Текст программы на ассемблере 1000: 012700 MOV #1777,R0 ;длительность звука 1002: 001777 ;(количество периодов) 1004: 012701 MOV #400,R1 ;длительность полупериода 1006: 000400 1010: 012737 M3: MOV #100,@#177716 ;первый полупериод 1012: 000100 1014: 177716 1016: 010102 MOV R1,R2 1020: 000240 M1: NOP 1022: 077202 SOB R2,M1 1024: 012737 MOV #0,@#177716 ;второй полупериод 1026: 000000 1030: 177716 1032: 010102 MOV R1,R2 1034: 000240 M2: NOP 1036: 077202 SOB R2,M2 1040: 077015 SOB R0,M3 При выполнении этого фрагмента программы машина издает короткий звук (периодический сигнал прямоугольной формы). Команда NOP, примененная в этом примере, никаких операций не производит ("холостая" команда). Но так как команда NOP выполняется за определенный промежуток времени, то она здесь использована для задания временных задержек в программе. Комбинация двух команд: MOV #100,@#177716 и MOV #0,@#177716 издает звук. Тон звука зависит от временных задержек между исполнениями этих двух команд. Фрагменты по адресам 1004, 1016- 1022 и 1032-1036 предназначены для задания временных задержек, определяющих тон звука. А команды MOV #1777,R0 и SOB R0,M3 задают длительность звука.
Команда 0001DD. Мнемокод: JMP
Команда JMP выполняет такие же действия, что и команда BR. Но если применение команды BR ограничено диапазоном смещений, то команду JMP можно использовать для перехода (передачи управления) на любой адрес программы. Поле адресации "DD" в коде команды задает не адрес операнда (поскольку операнда как такового в этой команде нет), а адрес, с которого будет продолжено выполнение программы после исполнения команды JMP. Поэтому в команде JMP недопустимо использование прямого регистрового способа адресации, так как передача управления на регистр процессора не имеет смысла. Пример1: 000137 JMP @#7000 007000 После выполнения этой команды программа продолжит свою работу с адреса 7000 - управление будет передано на адрес 7000. Пример 2: Адрес Команда Текст на ассемблере 5000: 000137 JMP @#МЕТ 5002: 007554 ... ... ... 7554: 005001 МЕТ: CLR R1 Пример 3: Адрес Команда Текст на ассемблере 5000: 000167 JMP МЕТ 5002: 002550 ... ... ... 7554: 005001 МЕТ: CLR R1 Результаты выполнения приведенных фрагментов программ одинаковы. Но в первом случае используется абсолютная адресация, а во втором - относительная. Если, например, весь участок программы с адреса 5000 по 7554 переместить в другое место ОЗУ, оператор JMP с относительной адресацией будет работать правильно, поскольку относительное смещение метки MET от команды JMP не изменится. А оператор с абсолютной адресацией отправит программу все равно на адрес 7554, и перемещенная программа будет работать неправильно. При работе с отладчиками типа ГРОТ, MIRAGE рекомендуем внутри каждого отлаженного куска программы использовать относительную адресацию, чтобы можно было весь этот кусок безбоязненно перемещать в памяти. А при работе на МИКРО годятся оба варианта, так как ассемблер при трансляции программы вычисляет адреса сам, а программист работает только с метками.
4.4.4.2. Команды для работы с подпрограммами
Их всего две: JSR ( Jump to Subroutine - перейти на подпрограмму ) и RTS ( Return from Subroutine - возврат из подпрограммы ).
Команда 004RDD. Мнемокод: JSR
Работа команды JSR напоминает работу оператора GOSUB в программе на языке Бейсик. По команде JSR адрес возврата (адрес команды, следующей за командой JSR) запоминается в регистре, номер которого указывается в коде команды 004RDD вместо буквы "R", а содержимое самого регистра процессора до этого запоминается в стеке (в специально отведенном месте ОЗУ ). Если в коде команды указан номер регистра R7 (цифра "7"), то адрес возврата запоминается в стеке. Назначение поля адресации "DD" в коде команды такое же, что и для команды JMP. Рекомендации по выбору режима адресации те же, что и для команды JMP - в программах (или участках программы), которые могут в процессе работы (или при отладке) перемещаться в ОЗУ, следует использовать относительную адресацию.
Команда 00020R. Мнемокод: RTS
Работа команды RTS напоминает работу оператора RETURN в программе на языке Бейсик. Команда RTS возвращает управление на адрес возврата, который по команде JSR был запомнен в регистре процессора. Номер этого регистра должен быть указан в коде данной команды 00020R вместо буквы "R". При выполнении команды содержимое указанного регистра загружается в счетчик команд, а сам регистр загружается значением, взятым из стека (обычно это то значение регистра, которое было запомнено при выполнении команды JSR). Если в коде команды указан регистр R7 (цифра "7"), то запомненный по команде JSR адрес возврата загружается в счетчик команд из стека. Пример: Адрес: Команда Мнемоника 4000: 004737 JSR PC,@#7500 4002: 007500 ... ... ... 7500: 012700 MOV #14,R0 7502: 000014 7504: 104016 EMT 16 7506: 000207 RTS PC Команда JSR PC,@#7500 передает управление на подпрограмму, начинаю- щуюся с адреса 7500. Возврат из подпрограммы производится командой RTS PC - выполнение основной программы продолжится с адреса 4004.
4.4.4.3. Команды прерываний
Таблица 14. Прерывания ┌───────────────┬─────────────────────────────────────┬──────────────┐ │ адрес вектора │ источник прерывания │тип прерывания│ │ прерывания │ │ │ ├───────────────┼─────────────────────────────────────┼──────────────┤ │ 4 │ нечетный адрес команды или │ аппаратное │ │ │ несуществующий адрес операнда; │ │ │ │ нажатие на клавишу "СТОП"; │ │ │ │ команда останова HALT │ программное │ │ 10 │ несуществующая команда │ программное │ │ 14 │ прерывание по T-биту PSW и по │ программное │ │ │ команде BPT │ │ │ 20 │ прерывание по команде IOT │ программное │ │ 24 │ авария сетевого питания │ аппаратное │ │ 30 │ команда EMT │ программное │ │ 34 │ команда TRAP │ программное │ │ 60 │ клавиатура │ аппаратное │ │ 100 │ прерыввание от внешнего таймера │ аппаратное │ │ 274 │ клавиатура при нажатой клавише "АР2"│ аппаратное │ │ 360 │ прерывание от приемника ИРПС │ аппаратное │ │ 364 │ прерывание от передатчика ИРПС │ аппаратное │ └───────────────┴─────────────────────────────────────┴──────────────┘ В процессе выполнения какой-либо программы на ЭВМ часто могут возникать не зависящие от нее события - например, нажатие на клавишу. Желательно, чтобы процессор сразу "обратил внимание" на такие события, а не ждал, пока программа "соизволит" проверить состояние внешнего устройства. Для этого предназначен механизм обработки прерываний. Он заключается в том, что при возникновении события выполнение программы временно прерывается и запускается программа обработки прерывания. Когда она выполнит все необходимые действия, выполнение основной программы продолжится. Источниками возникновения прерываний могут быть как сигналы внешних устройств (аппаратные прерывания), так и некоторые ситуации, возникающие при выполнении программы (программные прерывания). Некоторые из них перечислены в таблице 14. Каждый источник прерывания имеет свой вектор прерывания. Это адрес ОЗУ, по которому записан адрес программы обработки данного прерывания. Обычно прерывания обрабатываются монитором БК, но можно написать и свою программу обработки какого-либо прерывания. Для того, чтобы привести ее в действие, нужно будет записать адрес ее первой команды в соответствующий вектор прерывания. Чтобы обеспечить возврат к прерванной программе, в конце программы обработки прерывания должна стоять команда RTI (Return from Interrupt - возврат из прерывания). Код команды RTI - 000002. Команда RTT (код 000006) аналогична RTI, но предназначена для возврата из отладочного прерывания. Существует также ряд команд, которые вызывают программные прерывания по соответствующим векторам. К ним относятся: EMT (коды 104000-104377) - вызов системных подпрограмм; TRAP (коды 104400-104777) - вызов подпрограмм исполняющей системы (например, Бейсика, Фокала); IOT (код 000004) - прерывание для ввода-вывода (на БК практически не используется); BPT (код 000003) - прерывание для отладки.
4.4.4.3.1. Аппаратные прерывания
Рассмотрим пример возникновения прерывания от внешнего устройства (клавиатуры). Это, пожалуй, самый сложный и практически интересный случай прерывания. В момент нажатия клавиши устанавливается в 1 седьмой бит (бит готовности) в регистре состояния клавиатуры (по адресу 177760; см. п.п. 1.5.1, 1.5.2). Далее анализируется шестой бит (бит разрешения прерываний) того же регистра. Если он равен нулю (прерывания разрешены), то клавиатура выдает запрос на прерывание. Теперь дело за процессором. Он заканчивает выполнение текущей команды программы и анализирует бит P в РСП. Если он равен нулю, то процессор начинает обработку прерывания. Первым делом процессор помещает в стек текущее значение PSW, потом содержимое счетчика команд PC (а он, как Вы догадываетесь, показывает на следующую команду после только что выполненной). После этого процессор берет из соответствующего вектора прерывания (в данном случае из ячейки 60) адрес программы обработки прерывания и помещает его в PC, а из следующей по порядку ячейки 62 берет новое значение PSW и помещает его в РСП. Если в 62 ячейке было записано число 200, то теперь бит P в РСП будет установлен, и новое прерывание от клавиатуры не будет обрабатываться до тех пор, пока не закончится обработка данного прерывания. Стандартная программа обработки прерывания читает из регистра данных клавиатуры 177762 код нажатой клавиши (при этом сбросится бит готовности в регистре состояний клавиатуры). Также стандартная программа обработки издает звук, после чего с помощью команды RTI возвращает управление прерванной программе. По команде RTI процессор восстанавливает из стека сохраненное там содержимое PC и PSW, и программа продолжает свою работу. Обратите внимание, что в БК маскируются (то есть запрещаются установкой бита P в PSW) только прерывания от клавиатуры. Возникновение прерывания по клавише "СТОП" запретить нельзя. Пример 1. Организация перезапуска программы клавишей "СТОП". Здесь показано самое начало программы (все программы в кодах, как правило, начинаются с адреса 1000). Адрес Код команды Текст программы на ассемблере 1000 012706 MOV #1000,SP ;установить стек; 1002 001000 ;установить начальное 1004 104014 EMT 14 ;состояние экрана; 1006 012737 MOV #1000,@#4 ;теперь при нажатии 1010 001000 ;"СТОП" программа будет 1012 000004 ;запущена заново 1014 . . . ;продолжение программы Пример 2. Запрещение ввода символов по клавише "АР2". Это полезный прием, поскольку к таким символам относятся клавиши переключения режимов экрана "БЛ.РЕД", "ИНВ.ЭКР", "РП" и т.п., которые могут испортить изображение при работающей программе. ; эту команду можно вставить в начале программы (после команд ; предыдущего примера) MOV #TN,@#274 ;установить свою программу . . . ;обработки прерываний по "АР2"; ; а это - подпрограмма обработки прерывания по "АР2" TN: TST @#177762 ;снять готовность клавиатуры; RTI ;выйти из прерывания Пример 3. Работа с клавиатурой в режиме опроса регистра состояния. Работа с внешними устройствами (например, клавиатурой) может быть организована как с использованием прерываний (при этом достигается максимально быстрая реакция программы на событие), так и без использования прерываний - в режиме опроса регистра состояний. Последний способ применяют тогда, когда программа должна реагировать на события (например, на нажатие клавиш) только в определенные моменты. В игровых программах обычно имеет смысл управление движущимися объектами делать по прерываниям, а моменты диалога типа "вопрос-ответ" - в режиме опроса регистра состояния. В этом случае имеет смысл запретить стандартный механизм обработки прерываний, чтобы нажимаемые клавиши не портили картинку на экране; а перед ожиданием нажатия нужной клавиши "очистить входной буфер" клавиатуры, чтобы избежать неприятных последствий дребезга (повторного срабатывания) этого ненадежного устройства. Вот как это делается: ;начало программы MOV #100,@#177760 ;запретить прерывания . . . ;от клавиатуры ;ожидание ввода символа с предварительной очисткой буфера ввода TST @#177762 ;снять готовность клавиатуры; M: TSTB @#177760 ;ожидание ввода BPL M ;символа; MOVB @#177762,R0 ;принять код введенного символа . . . В этом примере командой TSTB @#177760 проверяется 7-й бит в регистре состояния клавиатуры (бит готовности). Используется тот факт, что 7-й бит для байта является знаковым, поэтому удобно использовать команду BPL (или BMI). Пример 4. Работа с клавиатурой по прерываниям. ;начало программы MOV #TI,@#60 ;задать адрес своей программы ;обработки прерываний; MOV #200,@#62 ;запретить прерывания на время . . . ;работы своей программы обработки ;все действия производятся в программе обработки прерывания TI: MOVB @#177762,R0 ;принять код нажатой клавиши; . . . ;сделать то, что нужно; RTI ;выйти из прерывания
4.4.4.3.2. Программные прерывания
Из всех перечисленных программных прерываний наибольшую практи- ческую ценность для программиста-любителя представляет прерывание по команде EMT. Процессор обрабатывает эту команду таким же образом, как если бы некое внешнее устройство выдало запрос на прерывание по векто- ру 30. Фактически же эта команда придумана специально, как кратчайший способ вызова системных подпрограмм. Дело в том, что команда EMT вы- полняется процессором одинаково независимо от содержимого младшего байта команды. Программа обработки прерывания (ее называют EMT-диспет- чером) использует младший байт команды EMT как номер подпрограммы из своей системной таблицы и вызывает ее. Свой набор EMT-команд характе- рен для каждой операционной системы (напомним, что функции операцион- ной системы в БК выполняет зашитый в ПЗУ МОНИТОР). Выгода при использовании EMT-команд такова: команда EMT вместе с номером вызываемой подпрограммы занимает одно слово, а обычный способ вызова подпрограмм комндой "JSR PC,адрес" требует двух слов памяти. Монитор БК обеспечивает выполнение следующих EMT-команд: EMT 4 - инициализация векторов прерывания клавиатуры; EMT 6 - чтение кода символа с клавиатуры (выходной параметр - код нажатой клавиши в R0); EMT 10 - чтение строки с клавиатуры. Входные параметры: R1 - адрес буфера, куда вводить строку; R2 - максимальная длина строки в младшем байте, символ-ограничитель в старшем байте. После записи в память очередного введенного символа содержимое R1 увеличивается на 1, а после окончания ввода в R2 будет разность между максимальной длиной и длиной введенной строки. Ввод строки прекращается, если длина строки станет равна максимальной, либо введен символ, указанный в старшем байте R2. Пример: 012701 MOV #2000,R1 ;расположить строку с адреса 2000; 002000 ;макс.длина строки = 100 байт, 012702 MOV #5100,R2 ;строка может быть закончена 005100 ;клавишей "ВК" (код 12 в старшем байте); 104010 EMT 10 ;ввести строку; 005702 TST R2 ;до конца ли введена строка? 001404 BEQ M 005301 DEC R1 ;уберем код 12 из введенной строки 005202 INC R2 112721 C: MOVB #40,(R1)+ ;и заполним остаток строки 000040 ;пробелами 077203 SOB R2,C M: . . . EMT 12 - установка ключей К1-К10 клавиатуры; вход: R0 - номер ключа от 1 до 10; R1 - адрес текста ключа, текст должен кончаться нулевым байтом; EMT 14 - инициализация экрана и установка всех векторов прерывания; EMT 16 - вывод символа; вход: код символа в R0; EMT 20 - вывод строки; вход: R1 - адрес строки; R2 - длина строки в младшем байте; символ-ограничитель в старшем байте; EMT 22 - вывод символа в служебную строку; вход: R0 - код символа (0 - очистка строки); R1 - номер позиции в служебной строке; EMT 24 - установка курсора по координатам X = R1, Y = R2; EMT 26 - получение координат курсора: R1 = X, R2 = Y; EMT 30 - рисование точки по координатам X = R1, Y = R2; R0 = 1 - запись точки, R0 = 0 - стирание; EMT 32 - рисование вектора (входные параметры те же, что и в EMT 30). Пример: ;привести экран в исходное состояние 104014 EMT 14 ;установить режим 32 символа в строке 012700 MOV #233,R0 000233 104016 EMT 16 ;нарисовать точку текущим (красным) цветом по координатам (0,0) 012700 MOV #1,R0 000001 005001 CLR R1 005002 CLR R2 104030 EMT 30 ;нарисовать зеленым цветом вектор из (0,0) в (111,111) 012737 MOV #125252,@#214 ;занести код зеленого цвета 125252 ;в служебную ячейку цвета 000214 012701 MOV #111,R1 000111 010102 MOV R1,R2 104032 EMT 32 EMT 34 - получение в R0 слова состояния дисплея, в котором каждый разряд является индикатором включения соответствующего режима (табл.15): 0 - выключено, 1 - включено; Таблица 15. Слово состояния дисплея ┌───────────────┬────────────────────────────────────────────┐ │ номер разряда │ соответствующий режим │ ├───────────────┼────────────────────────────────────────────┤ │ 0 │ Режим "32 символа в строке" │ │ 1 │ Инверсия экрана │ │ 2 │ Режим расширенной памяти ( РП ) │ │ 3 │ Русский регистр │ │ 4 │ Подчеркивание символа │ │ 5 │ Инверсия символа │ │ 6 │ Индикация "СУ" │ │ 7 │ Блокировка редактирования │ │ 8 │ Режим текстовой графики "ГРАФ" │ │ 9 │ Запись в режиме "ГРАФ" │ │ 10 │ Стирание в режиме "ГРАФ" │ │ 11 │ Режим "32 символа в служебной строке" │ │ 12 │ Подчеркивание символа в служебной строке │ │ 13 │ Инверсия символа в служебной строке │ │ 14 │ Гашение курсора │ │ 15 │ Не используется │ └───────────────┴────────────────────────────────────────────┘ EMT 36 - работа с магнитофоном; в R1 задается адрес блока параметров (обычно блок параметров задается с адреса 320). Формат блока параметров показан в таблице 16. Если при загрузке задать адрес, равный нулю, то программа (массив) будет загружаться с адреса, указанного на ленте. После успешной загрузки файла адрес загрузки и длина массива записываются также по адресам 264, 266. Таблица 16. Формат блока параметров для работы с магнитофоном ┌───────┬───────┬───────────────────────────────────────────────┐ │ номер │ адрес │ содержание │ │ байта │ │ │ ├───────┼───────┼───────────────────────────────────────────────┤ │ 0 │ 320 │ команда: 0 - стоп двигателя, │ │ │ │ 1 - пуск │ │ │ │ 2 - запись массива на ленту │ │ │ │ 3 - чтение массива с ленты │ │ │ │ 4 - фиктивное чтение (поиск) │ │ 1 │ 321 │ код завершения операции: │ │ │ │ 0 - без ошибок │ │ │ │ 1 - не то имя массива │ │ │ │ 2 - ошибка контрольной суммы │ │ │ │ 3 - останов по клавише "СТОП" │ │ 2 │ 322 │ адрес массива в ОЗУ (слово) │ │ 4 │ 324 │ длина массива на запись (слово) │ │ 6 │ 326 │ имя массива (16. байт) │ │ 22 │ 346 │ адрес обнаруженного на ленте массива │ │ 24 │ 350 │ длина обнаруженного на ленте массива │ │ 26 │ 352 │ имя обнаруженного на ленте массива (16. байт) │ └───────┴───────┴───────────────────────────────────────────────┘ Аналогично EMT действует и команда TRAP, только по другому вектору. Эту команду используют обычно исполняющие системы интерпретаторов (Бейсик, Фокал и пр.) для своих внутренних целей. Например, в Фокале команда TRAP с нечетным кодом в младшем байте выдает соответствующий этому коду текст сообщения об ошибке, а с четным - вызывает соответствующую подпрограмму. Программист может написать сам TRAP-диспетчер для своей программы, а может с разными целями перехватывать и системные командные прерывания. Например, первые Фокоды брали на себя вектор прерывания по EMT. После этого появлялась возможность вызывать подпрограммы в кодах из программы на Фокале при выводе на дисплей "непечатных" символов (0, 1, 2 и т.д.). При выводе символа Фокал выполняет команду "EMT 16", Фокодовская программа обработки прерывания проверяет, какая EMT- команда вызвала прерывание, и если ее номер 16 и выводимый код символа меньше 7, например, то вызывается подпрограмма в кодах; а иначе управление возвращается в системный EMT-диспетчер. Современные расширители Фокала и Бейсика используют вектор прерывания по TRAP, анализируют адрес команды во "внутренностях" Фокала (Бейсика), которая вызвала это прерывание и, при необходимости, сами выполняют аналогичные вызываемым подпрограммы, но по-другому - так, как нужно данному расширителю. Приведем пример простейшего TRAP-диспетчера, который Вы можете использовать в своих программах для упрощения вывода символов. Для его понимания напомним, что выполняются командные (программные) прерывания так же, как и аппаратные - сначала в стеке сохраняется текущее состояние PSW, затем - адрес следующей команды, куда после обработки прерывания необходимо вернуться. ; в начале программы установим свой вектор прерывания по TRAP MOV #TRA,@#34 ; теперь в программе можно использовать команду TRAP TRAP 101 ;вывести символ "А" (его код равен 101) TRAP 60 ;вывести символ "0" (код 60) . . . ; наша программа обработки прерывания по TRAP TRA: MOV R0,-(SP) ;сохраним регистр в стеке MOV 2(SP),R0 ;получим из стека адрес возврата, который ;сохранен там командой TRAP MOV -(R0),R0 ;поместить в R0 саму команду - виновницу ;прерывания EMT 16 ;вывести на экран символ из младшего байта MOV (SP)+,R0 ;восстановить R0 RTI ;выйти из прерывания Обратите внимание: обычно для вывода символа нужно было использовать две команды, занимающие три слова: MOV #101,R0 EMT 16 а теперь достаточно одной однословной команды "TRAP 101". При частом применении такой конструкции можно получить существенную экономию памяти. Заметим также, что часто используется и прерывание по вектору 10 - недопустимая команда. Обычно это прерывание используется программами, эмулирующими команды умножения, деления и плавающей арифметики (поскольку у процессора БК нет таких команд).
4.4.5. Безоперандные команды
Таблица 17. Безоперандные команды ┌──────────────┬──────────┬─────────────────────────────────────┐ │ восьмеричный │ мнемокод │ действие команды │ │ код команды │ команды │ │ ╞══════════════╪══════════╪═════════════════════════════════════╡ │ 000000 │ HALT │ Halt - останов │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000001 │ WAIT │ Wait - ждать │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000005 │ RESET │ Reset - сброс │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000240 │ NOP │ No OPeration - нет операции │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000241 │ CLC │ Clear C - очистить С ( разряд PSW ) │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000242 │ CLV │ Clear V - очистить V │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000244 │ CLZ │ Clear Z - очистить Z │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000250 │ CLN │ Clear N - очистить N │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000257 │ CCC │ Clear Condition Code - очистить коды│ │ │ │ условий │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000261 │ SEC │ Set C - установить C │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000262 │ SEV │ Set V - установить V │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000264 │ SEZ │ Set Z - установить Z │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000270 │ SEN │ Set N - установить N │ ├──────────────┼──────────┼─────────────────────────────────────┤ │ 000277 │ SCC │ Set Condition Code- установить коды │ │ │ │ условий │ └──────────────┴──────────┴─────────────────────────────────────┘ Здесь будут рассмотрены команды управления машиной и команды установки разрядов PSW. Все эти команды приведены в таблице 17.
4.4.5.1. Команды управления машиной
Команда 000000. Мнемокод: HALT
Вызывает прерывание по вектору 4 аналогично клавише "СТОП".
Команда 000001. Мнемокод: WAIT
По этой команде процессор временно прекращает выполнение программы и переходит в режим ожидания прерывания. После того, как произойдет прерывание от внешнего устройства (например, от клавиатуры), процессор обработает прерывание, и выполнение программы продолжится с команды, следующей за командой WAIT.
Команда 000005. Мнемокод: RESET
По этой команде все внешние устройства устанавливаются в состояние, которое они имеют после включения питания, после чего процессор возобновляет работу.
Команда 000240. Мнемокод: NOP
По этой команде процессор не выполняет никаких действий и переходит к выполнению следующей команды. Эта команда может использоваться при отладке программы в кодах для замены нескольких удаляемых команд, а также для создания временных задержек при работе программы.
4.4.5.2. Команды установки разрядов PSW
Эти команды предназначены для установки в "1" или очистки (сброса в "0") отдельных разрядов PSW. В мнемокоде каждой из 4-х команд CLC, CLV, CLZ, CLN первые 2 буквы "CL" указывают на то, что команда производит очистку одного разряда PSW. 3-я буква указывает на очищаемый разряд. Например, команда CLZ очищает разряд Z PSW. Команда ССС одновременно очищает разряды С,V,Z,N PSW. Первые 2 буквы "SE" в мнемокодах команд SEC, SEV, SEZ, SEN указывают на то, что каждая из этих команд предназначена для установки в "1" отдельного разряда PSW, заданного 3-ей буквой мнемокода. Команда SCC одновременно устанавливает в "1" разряды С,V,Z,N PSW.
4.5. Использование стека
Стеком может служить любая свободная область ОЗУ. Под стеком понимается область ОЗУ, адресация к ячейкам которой осуществляется определенным образом. Стандартный способ работы со стеком, который используют и все команды прерываний и подпрограмм, осуществляется с помощью регистра SP (Stack Pointer - указатель стека). Стек используется программистом для временного хранения промежуточных данных программы. При записи слова в стек используется автодекрементный способ адресации, а при извлечении из стека данных - автоинкрементный. Процессор использует стек для временного хранения адреса возврата из подпрограммы (или содержимого какого-либо регистра), а также при обработке прерывания. При этом запись в стек и считывание из стека производятся процессором аппаратно. Перед выполнением команд, использующих стек, в регистр SP процессора необходимо предварительно записать адрес начала стека (настроить стек). Например, транслятор с языка Бейсик, зашитый в ПЗУ, использует стек, начинающийся с адреса 2000, а все обычные программы в кодах - с адреса 1000. На рисунке 20 показано выполнение записи в стек по команде "MOV R3,-(SP)". Пусть до выполнения команды MOV регистр SP содержит адрес 1754, а в R3 было записано число 132. Затем указатель стека уменьшается на 2 и содержимое регистра R3 (число 132) записывается по адресу 1752. С увеличением размеров стека уменьшается содержимое регистра SP - стек растет в сторону младших адресов. ┌──────┬───────────┐ ┌──────┬──────────┐ │адрес │содержимое │ │адрес │содержимое│ │ ОЗУ │ │ │ ОЗУ │ │ ╞══════╪═══════════╡ ╞══════╪══════════╡ │ 1756 │ 17 │ │ 1756 │ 17 │ ├──────┼───────────┤ ├──────┼──────────┤ SP ─->│ 1754 │ 23 │ │ 1754 │ 23 │ ├──────┼───────────┤ ├──────┼──────────┤ │ 1752 │ │ SP ──>│ 1752 │ 132 │ ├──────┼───────────┤ ├──────┼──────────┤ │ │ │ │ │ │ а) б) Рис. 20. Запись в стек: а) до выполнения команды; б) после выполнения команды На рисунке 21 приведен пример чтения из стека. До выполнения команды "MOV (SP)+,R3" регистр SP содержит адрес 1752. По указанной команде из слова, адрес которого хранится в SP, число 132 пересылается в регистр R3, после чего содержимое регистра SP увеличивается на 2. ┌──────┬──────────┐ ┌──────┬──────────┐ │ адрес│содержимое│ │адрес │содержимое│ ╞══════╪══════════╡ ╞══════╪══════════╡ │ 1756 │ 17 │ │ 1756 │ 17 │ ├──────┼──────────┤ ├──────┼──────────┤ │ 1754 │ 23 │ SP ──>│ 1754 │ 23 │ ├──────┼──────────┤ ├──────┼──────────┤ SP ──>│ 1752 │ 132 │ │ 1752 │ 132 │ ├──────┼──────────┤ ├──────┼──────────┤ │ │ │ │ │ │ а) б) Рис. 21. Чтение из стека: а) до выполнения команды; б)после выполнения команды
4.6. ОЗУ экрана
ОЗУ экрана (видеопамять) занимает область памяти с адреса 40000 по адрес 77777. На рисунке 22 показано соответствие адресов видеопамяти определенным участкам на экране. Например, левому верхнему углу экрана соответствует адрес 40000 видеопамяти, а нижнему правому углу - адрес 77777. Для того, чтобы вывести какое-либо изображение на определенный участок экрана, достаточно записать по соответствующему адресу ╔═══════╤═══════╤═══════╤═══════╤═════ ═════╤═══════╤═══════╗ ║ 40000 │ 40001 │ 40002 │ 40003 │ . . . │ 40076 │ 40077 ║ ╟───────┼───────┼───────┼───────┼── ──┼───────┼───────╢ ║ 40100 │ 40101 │ 40102 │ 40103 │ . . . │ 40176 │ 40177 ║ ╟───────┼───────┼───────┼───────┼── ──┼───────┼───────╢ ║ ║ . . . . . . ║ ║ ╟───────┼───────┼───────┼───────┼── ──┼───────┼───────╢ ║ 77600 │ 77601 │ 77602 │ 77603 │ . . . │ 77676 │ 77677 ║ ╟───────┼───────┼───────┼───────┼── ──┼───────┼───────╢ ║ 77700 │ 77701 │ 77702 │ 77703 │ . . . │ 77776 │ 77777 ║ ╚═══════╧═══════╧═══════╧═══════╧═════ ═════╧═══════╧═══════╝ Рис. 22. Соответствие адресов видеопамяти определенным участкам на экране. видеопамяти число, определяющее вид данного изображения. Например, чтобы на участке экрана, соответствующем адресу 56036, высветить точки, расположение которых показано на рисунке 23, достаточно переслать по адресу 56036 двоичный байт 10010011 (восьмеричное число 223). На языке ассемблера такая пересылка выражается командой MOVB #223,@#56036 ╔═══════╦═══════╦═══════╦═══════╗ ║красная║ черная║ синяя ║зеленая║ <── расположение точек при ╟───┬───╫───┬───╫───┬───╫───┬───╢ цветном изображении ║ ▓ │ ▓ ║ │ ║ ▓ │ ║ │ ▓ ║ <── расположение точек при ╟───┼───╫───┼───╫───┼───╫───┼───╢ черно-белом изображении ║ 1 │ 1 ║ 0 │ 0 ║ 1 │ 0 ║ 0 │ 1 ║ <── содержимое разрядов байта ╟───┼───╫───┼───╫───┼───╫───┼───╢ ║ 0 │ 1 ║ 2 │ 3 ║ 4 │ 5 ║ 6 │ 7 ║ <── номера разрядов байта ╚═══╧═══╩═══╧═══╩═══╧═══╩═══╧═══╝ Рис. 23. Пример изображения байта на экране Разряды байта выводятся на экран (слева направо), начиная с младшего разряда двоичного числа, что доставляет некоторые неудобства программисту. Все сказанное выше верно только в том случае, если изображение выводится на черно-белый экран - тогда единичным битам выводимого байта соответствуют белые точки на экране, а нулевым битам - черные. Если же изображение выводится на цветной экран, то в формировании каждой "цветной" точки участвуют по 2 двоичных разряда. Красную точку дает комбинация разрядов 11, зеленую - 01, синюю - 10, и черную - 00. Из этого следует, что в одном байте можно запрограммировать информацию о 8-ми "черно-белых" точках или о 4-х "цветных" точках. Изображение, занимающее полную площадь экрана состоит из 256Д точечных строк. В формировании одной строки участвуют 64Д байта видеопамяти. Например, для формирования начальной (самой верхней) строки экрана выделена область памяти с адресами от 40000 до 40077. Верхяя часть экрана с адреса 40000 по 41777 используется для формирования служебной строки. Точка с графическими координатами X=0, Y=0 находится в младших разрядах байта по адресу 42000.