Программирование на БК-0010-01/Глава 4

Материал из Emuverse
Версия от 11:16, 19 ноября 2007; Panther (обсуждение | вклад) (http://www.vak.ru/doku.php/proj/bk/bk4prog)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Данный материал защищён авторскими правами!

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

Программирование в машинных кодах

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.