Глава 2. Общие принципы экранного вывода в УКНЦ.

§4. Программные прерывания EMT И TRAP.

4.0 Команды-прерывания.

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

Таблица 4.0. Команды-прерывания.

Команда

Код

А.В.П.

BPT 000003 14
IOT 000004 20
EMT 104xYZ 30
TRAP 104XYZ 34

Пример 11. Упражнение с командами-прерываниями IOT и EMT.

Команда IOT (Input-Output Trap) вызывает прерывание с адресом 20. В Системе этот а.в.п. никак не используется. Восполним же этот пробел. Работаем в ОЗУ ПП:

20:     000240

240:    104044 EMT 44
        163573 "* ЗАГРУЗКА ИЗ СЕТИ *"
        000002 RTI

Теперь в любую свободную ячейку запишите число 4 (код IOT) и запустите с этого адреса. Ну, а если Вам наскучит играться с этой надписью, в приложении найдите другую, и адрес ее запишите после кода EMT 44. А еще лучше - читайте дальше.

Первые две команды (BPT и IOT) нам неинтересны, хотя при желании и их можно пустить в дело. Две остальные - EMT и TRAP - представляют некоторый интерес.

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

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

Рассмотрим реализацию обоих диспетчеров в Системе.

4.1 EMT-диспетчер.

По адресу 30 записан вектор прерывания EMT-дипетчера:

30:   174270
32:   000000

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

Ниже приведена блок-схема EMT-диспетчера с пояснениями:

wpe9.jpg (18640 bytes)

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

Адр=(160000+XXX), где XXX - младший байт EMT.

Иными словами, с адреса 160000 хранится таблица, в которой содержатся адреса искомых подпрограмм. Разумеется, младший байт EMT должен быть четным, во избежание недоразумений в процессоре.

В адресах ПЗУ с 160000 по 160012 хранятся некоторые вектора прерываний, поэтому используются EMT с младшими байтами, начиная с 14. Полезных подпрограмм, вызываемых EMT-диспетчером, всего 10. Перечень их приведен в приложении. Остальные подпрограммы состоят из одной команды - RETURN.

 

 

4.2 TRAP-диспетчер.

Вектор TRAP-диспетчера записан по адресу 34:

34:    174344
36:    000200

Второе слово говорит о том, что во время работы TRAP-диспетчера будут запрещены прерывания от сетевого и программируемого таймеров, от клавиатуры, от команды RESET в ЦП, от прерываний каналов.

Блок-схема TRAP-диспетчера выглядит так:

wpe7.jpg (10930 bytes)

Адрес подпрограммы вычисляется так:

Адр=(160160+XXX), где XXX - младший байт TRAP.

Т.е. адреса подпрограмм хранятся с адреса 160160. Этих подпрограмм всего 3, т.е. имеют смысл лишь три команды TRAP:

TRAP 0,
TRAP 2,
TRAP 4.

Отличие их от EMT-подпрограмм в том, заканчиваться они должны на RTI, а не на RETURN.

 

Резюме к §4:

 


§5. Общая схема вывода на экран.

5.0 Буфер и его структура .

Информация на экран отправляется побайтно. Каждый процессор может иметь доступ к выводу символьной и графической информации на терминал. Для этого у каждого процессора свой путь.

ЦП посылает информацию через К0. ПП отправляет ее через команды EMT. Но в любом случае эти байты записываются в особую область ОЗУ ПП, называемую буфером. Он находится в адресах с 2000 по 2177 (200 байт).

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

Переменная в ОЗУ ПП (22544) является указателем на "хвост" этой очереди. То есть она содержит адрес ячейки, куда будет записана очередная поступившая посылка (от ЦП или ПП).

 

5.1 Запись в буфер из К0.

При записи из ЦП в канал К0 при разрешенном прерывании от приемника в ПП выполняется прерывание с а.в.п. 320. Если прерывания запрещены, тогда есть другой способ считать информацию из К0 в буфер - это команда TRAP 4. Тогда, если посылка действительно была (установлен бит готовности в приемнике), информация считывается в буфер из соответствующего регистра данных.

И п.о.п от К0, и TRAP 4 - это, по сути, одна и та же программа, но с разными точками входа (схема 5.1).

wpeA.jpg (21308 bytes)Здесь используется еще несколько переменных. Смысл их в следующем:

Таблица 5.1

Адрес Назначение
7042 Разрешает либо запрещает связь с ЦП через К0:

0 - связь запрещена,
1 - связь разрешена.

7064 Счетчик байт, подлежащих обработке. Может содержать от 0 до 177.
22546 Признак переполнения буфера. Если (7064)=177, и поступает новый байт, запись его в буфер не производится, а (22546) присваивается 2 (переполнение). Сбрасывается через TRAP 4.

5.2 Запись в буфер из ПП.

Буфер может пополняться также из ПП. Для этого могут использоваться три команды: EMT 42, EMT 44 и EMT 46.

EMT 42 записывает в буфер младший байт R0, EMT 44 - строку, адрес которой содержится в слове, следующем за командой, а EMT 46 - строку с адресом в R1.

На схемах 5.2 и 5.3 показано выполнение этих команд. Поскольку EMT - подпрограммы можно вызывать и через CALL, на схеме показаны и адреса дополнительных точек входа.

wpeB.jpg (14601 bytes)

Если выполнить, к примеру, такой отрывок программы:

        JSR R5,@#117204
        .WORD A
        .
        .
A: ASCIZ /*** ЗАЧЕМ ВАМ EMT 44? ***/

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

        EMT 44
        .WORD A
        .
        .
A:      ASCIZ /*** ЧТО БЫ ВЫ БЕЗ EMT 44 ДЕЛАЛИ? ***/

поскольку минуется вызов EMT-диспетчера.

Заметим, что с указателем буфера после увеличения выполняется команда &~200, что предотвращает выход его за значение 2177.

wpeC.jpg (29679 bytes)

Резюме к §5:

Таблица 5.2

Что пишем и откуда

Способы достижения

С немедленным выводом

Без такового

1 байт из R0 EMT 42 CALL @#117136
Строка, адрес которой в R1 EMT 46 JSR R5, @#117206
Строка, адрес которой - A EMT 44
WORD A
JSR R5, @#117204
.WORD A

Способы с немедленным выводом на экран отличаются выполнением TRAP 0 в конце подпрограммы.

 


§6. TRAP 0, или Диспетчер процессов. Стратегия управления.

6.0 Схема Диспетчера процессов.

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

TRAP 0 можно назвать также и диспетчером процессов, который координирует работу внешних устройств, подстраивая под их нужды (и под нужды пользователя, в конце концов) все ресурсы, зашитые в ПЗУ.

Сама подпрограмма TRAP 0 немногословна. Она просто коротка (можете взглянуть на схему 6.0). Однако разобраться в ее работе сразу будет довольно трудно. Поэтому упрощенно рассмотрим "стратегию управления" в ОЗУ ПП.

wpe10.jpg (23210 bytes)

6.1 Стратегия управления.

Проследим, что происходит в УК при включении питания.

  1. Запускается ПП и начинает работу с адреса 160300. Это стартовый адрес программы начального запуска (ПНЗ).
  2. ПНЗ останавливает ЦП (на всякий случай), копирует в СОЗУ ЦП программы, необходимые ЦП для нормальной работы, и запускает ЦП.
  3. Затем идет тестовый контроль памяти и процессоров. Результаты его запоминаются.
  4. Выполняется инициализация внешних и внутренних устройств, к ним подвешиваются стандартные прерывания, создается ОЗУ ПП (т.е. загружаются начальные значения некоторых переменных). Отметим, что инициализация экрана выполняется с помощью EMT 40.
  5. По результатам стартового теста в случае ошибки выдается сообщение-диагноз, например: "Стартовый тест Ошибка ПЗУ 2", сигнализируя о том, что неисправен 2-й банк СПЗУ.
  6. Идет переход к диспетчеру процессов, в точку @.(Будем различать TRAP 0 и диспетчер процессов точкой входа. Если происходит вход в точку @, будем считать, что работает диспетчер процессов).

Далее вся работа ПП идет через диспетчер процессов. Как это происходит?

 

6.2 Запросы. Таблицы запросов и процессов.

Есть в ОЗУ ПП таблица по адресам с 7060 по 7102. Назовем ее таблицей запросов и попробуем объяснить это название.

Каждому слову в таблице соответствует своя задача:

7060 - обработка информации, поступающей от клавиатуры,
7062 - загрузка с ВУ,
7064 - экранный вывод,
7066 - управление курсором,
7070 - меню "Установка режимов",
7072 - меня "Загрузка",
7074 - работа с принтером,
7076 - запуск подпрограммы пользователя,
7100 - тестирование,
7102 - выход в диспетчер процессов (обратно).

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

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

Эта таблица расположена в ПЗУ по адресам 174232...174252, т.е. содержит 9 адресов. Последней ячейке таблицы запросов 7102 не соответствует адреса в таблице адресов процессов.

Как и когда изменяется содержимое таблицы запросов? Мы уже встречались с ячейкой 7064 - каждый раз при записи в буфер байта она инкрементируется. Как видно из таблицы, эта ячейка действительно отвечает за экранный вывод. Если она установлена (не равна 0), диспетчер запускает подпрограмму экранного вывода, и та уже обрабатывает записанную в буфер информацию, вычитая из (7064) единицу после каждого обработанного байта .Это повторяется до тех пор, пока ячейка не обнулится. Тогда происходит возврат в диспетчер процессов и сканирование продолжается.

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

Увеличение или установка запросов ведется "со стороны", в основном, по прерываниям: от клавиатуры, от каналов, от сетевого таймера.

Ячейка с адресом 7102 - последняя из таблицы запросов - не меняет своего значения - 1, и служит для возобновления цикла диспетчера процессов.

 

6.3 Таблица векторов. Вызов процессов через TRAP 0.

Сразу за таблицей запросов в ОЗУ следует еще одна таблица - таблица векторов. Если идет выполнение одного из процессов, и из него надо выполнить другой процесс, не завершая текущего, то вызывается TRAP 0 (как это делается из EMT 44, например). Вектор прерванного процесса, а точнее, текущий адрес переписывается в таблицу векторов. В ней каждой ячейке также соответствует процесс. Разница адресов "одноименных" ячеек таблицы запросов и таблицы векторов составляет 24.

Выполнив процесс, для которого он был вызван, TRAP 0 находит установленную ячейку в таблице запросов. В зависимости от содержания таблицы векторов (а точнее, той ее ячейки, которой соответствует установленный запрос) TRAP 0 либо возвращается в прерванный старый процесс через JMP (в таблице векторов - ненулевой вектор), либо запускает процесс через CALL (в таблице векторов - 0).

Небольшая тонкость: TRAP 0 не может выполнить процесс, стоящий "ниже" того, из которого он был вызван. То есть вызванный из программы вывода на экран (адрес запроса - 7064), он не дойдет до запросов, адреса которых больше 7064 и может обработать только клавиатуру и внешние устройства. Поэтому процессы расположены в порядке убывания важности.

Пример 12. Перехват запросов.

Таблица векторов - самая удобная лазейка для перехвата обработки запросов на процессы. Попробуем перехватить обработку запросов на процесс отслеживания курсора.

В мониторе ПП запишите следующее:

41000:  042737 BIC #200, @#177716
        000200
        177716
        052737 BIS #200, @#177716
        000200
        177716
        004737 CALL @#176056
        176056
        012737 MOV #41000, @#7112
        041000
        007112
        000137 JMP @#174222
        174222

7112:   041000

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

 

6.4 Внутренние и внешние процедуры.

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

Внешние процедуры не имеют права вызывать TRAP 0, это приведет к тому, что диспетчер процессов "вылетит" из цикла и машина подвиснет.

Адреса таблиц запросов векторов, а также содержимое таблицы задач приведены в таблице 6.0:

Таблица 6.0.

N Процесс Адрес запроса Адрес вектора Адрес процесса
1 Терминальный ввод 7060 7104 104306
2 Загрузка с ВУ 7062 7106 125030
3 Терминальный вывод 7064 7110 111144
4 Управление курсором 7066 7112 176056
5 Меню "Установка режимов" 7070 7114 100040
6 Меню "Загрузка" 7072 7116 100742
7 Работа с принтером 7074 7120 176076
8 Подпрограмма пользователя 7076 7122 176116
9 Тестирование 7100 7124 176460
10 Цикл диспетчера процессов 7102 7126 -

Пример 13. Перехват цикла диспетчера процессов. Способ 1.

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

Наш процесс останется тем же - щелчок:

41100:  042737 BIC #200, @#177716
        000200
        177716
        052737 BIS #200, @#177716
        000200
        177716
        000137 JMP @#174230
        174230

7112:   000000
7126:   041100

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

 

Пример 14. Перехват цикла диспетчера процессов. Способ 2.

Посмотрим, что произойдет , если обнулить вектор рестарта диспетчера процессов: (7126)=0. Тогда диспетчер станет обрабатывать процесс рестарта через CALL, взяв адрес из таблицы адресов процессов в ПЗУ. Но такого адреса для процесса рестарта на предусмотрено, и диспетчер возьмет первую ячейку после таблицы. Ее содержимое - 13700, а значит, произойдет вызов подпрограммы по адресу 13700. Это и есть второй способ вывести цикл диспетчера на свою концовку. Выход из этой концовки должен осуществляться через RETURN.

13700:  000137 JMP @#41200
        041200

41200:  042737 BIC #200, @#177716
        000200
        177716
        052737 BIS #200, @#177716
        000200
        177716
        000207 RETURN

7126:   000000

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

 

Резюме к §6:

    1. Программа начального запуска.
    2. Диспетчер процессов (он же TRAP 0).
    3. Программы обработки прерываний.
    4. Все остальное.

Все, что входит в пункт 4, вызывается диспетчером процессов.

1) внутренние по отношению к диспетчеру процессов (сами процессы),

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