Д.Ю. Усенков
Дополнительные возможности EMT-прерывания БК-0010
Одним из способов вызова подпрограмм в системе машинных команд БК-0010 является так называемое EMT-прерывание. Механизм вызова подпрограммы в данном случае общий с механизмом обработки прерываний от внешнего источника (клавиатуры или порта ввода-вывода) или внутренней функции (TRAP или HALT): в стек загружается регистр ССП (доступный только группе специальных команд Ассемблера, например, MTPS; MFPS; CLc, где с - код условия, и т.п.) и отражающий текущее состояние процессора и адрес ячейки ОЗУ, где находится следующая по порядку машинная команда. Из особой области стека (область векторов прерываний) извлекаются записанные там адрес входа в вызываемую подпрограмму и состояние процессора при её выполнении.
После отработки подпрограммы по команде RTI из стека восстанавливается состояние процессора и содержимое счётчика команд (адрес продолжения основной программы). Адрес ячеек стека с записью адреса входа в подпрограмму обработки прерывания и ССП (вектор прерывания) БК определяет сама, в зависимости от причины прерывания. Основное отличие такого способа вызова подпрограмм от обычного в Ассемблере оператора JSR состоит в том, что команда вызова EMT на одно машинное слово короче, чем команда JSR (первое слово - код самой этой команды и указание типа адресации, а второе - адрес начала подпрограммы).
Для программ большого объёма, когда уже сказывается дефицит оперативной памяти, и при большом количестве вызовов одних и тех же подпрограмм это отличие весьма существенно. Кроме того, запомнить номер EMT-функции для типовых подпрограмм проще, чем соответствующий адрес входа. Поэтому EMT-функции широко используются для вызова стандартных, заложенных в Монитор БК подпрограмм-операций, таких, как ввод с клавиатуры или печать на экране символа или строки, построение точки или линии, вывод или ввод программы на магнитофон и т.д. в трансляторах с Бейсика и Фокала и в различных пользовательских программах. При этом используются EMT-функции с номерами от 4 до 36 (все номера восьмеричные), а в имеющей блок ИРПС БК-0010Ш - EMT 40 - EMT 50.
Попытка использовать EMT-функции для вызова своих подпрограмм, расположенных в пользовательской области ОЗУ, наталкивается на одну основную сложность: для этого нужно писать свой драйвер EMT-прерываний, который берет на себя распределение вызываемых подпрограмм в зависимости от номера EMT-функции. Правда, разработчиками БК всё же оставлены резервные EMT-функции с номерами 52 - 110 и соответственно адресами входов с 1600008 по 1600748. Но эти адреса относятся к ПЗУ, их можно использовать только в старом варианте БК-0010 (только с Фокалом) и только с учётом использования пользовательской (сменной) кассеты ПЗУ. В БК-0010.01 такого разъёма для сменной кассеты ПЗУ нет, к тому же и Бейсик занимает указанную область памяти.
Однако заложенный в монитор БК драйвер EMT-прерываний (для интересующихся: вектор прерывания по EMT - @#308; адрес начала драйвера: 1001128) может обрабатывать EMT-функции с любым номером из диапазона от 0 до 3778 включительно. Сущность работы этого драйвера - выделить из команды EMT её номер - младший байт, поместить в регистр R5 адрес вызова подпрограммы - он записан в ПЗУ в ячейке с адресом 100000+N, где N - номер EMT и вызвать с помощью команды JSR R7,@R5 нужную подпрограмму. Если номер EMT соответствует обычно применяемому, то в качестве адреса вызова будет взято число из списка адресов (ПЗУ, адреса от 1000048 до 1001108). Если указать какой-либо другой номер, то в качестве адреса будет взят код какой-либо из команд Монитора «по соседству» с указанным списком.
Кроме того, необходимо заметить, что в БК-0010 операции с нечётным адресом выполняются только над байтами, тогда как в операциях с двухбайтными машинными словами все нечётные адреса корректируются процессором при их обработке: адрес преобразуется в чётный, меньший исходного на единицу (это соответствует ссылке на младший байт того же машинного слова). Поэтому функции EMT с нечётными номерами идентичны EMT-функциям с номерами чётными: EMT 1 = EMT 0, EMT 3 = EMT 2, EMT 13 = EMT 12 и т.д. Учитывая это правило, можно предложить следующую таблицу дополнительных EMT-функций. В таблице 1 указаны номера функций, которые можно практически использовать, адреса входов в подпрограммы и указание-комментарий к применению. Некоторые из таких EMT-функций передают управление не в ОЗУ пользователя, а в ПЗУ, в ОЗУ экрана, в область стека и векторов прерываний, то есть места, где нельзя разместить свою подпрограмму - список этих EMT-функций приводится в таблице 2.
№№ |
Адрес входа |
Примечание |
№№ |
Адрес входа |
Примечание |
---|---|---|---|---|---|
112 |
10546 |
ОЗУП |
114 |
16604 |
ОЗУП |
120 |
14504 |
ОЗУП |
122 |
42704 |
ОЗУП/РП |
126 |
16504 |
ОЗУП |
130 |
100000 |
Перезапуск БК |
132 |
4714 |
ОЗУП |
134 |
12604 |
ОЗУП |
140 |
5000 |
ОЗУП |
142 |
12702 |
ОЗУП |
146 |
12720 |
ОЗУП |
150 |
100000 |
Перезапуск |
154 |
12736 |
ОЗУП |
162 |
12736 |
ОЗУП |
164 |
100112 |
Вход в драйвер EMT |
170 |
12736 |
ОЗУП |
176 |
12702 |
ОЗУП |
202 |
5020 |
ОЗУП |
210 |
5266 |
ОЗУП |
214 |
105267 |
Примечание 1 |
220 |
5166 |
ОЗУП |
224 |
5166 |
ОЗУП |
230 |
4766 |
ОЗУП |
232 |
4466 |
ОЗУП |
234 |
5000 |
ОЗУП |
236 |
104040 |
Примечание 1 |
240 |
5036 |
ОЗУП |
244 |
12736 |
ОЗУП |
260 |
12706 |
ОЗУП |
262 |
1000 |
ОЗУП |
264 |
4766 |
ОЗУП |
270 |
4736 |
ОЗУП |
272 |
120000 |
Вход в Бейсик |
274 |
4766 |
ОЗУП |
300 |
12702 |
ОЗУП |
304 |
4766 |
ОЗУП |
310 |
104006 |
Примечание 3 |
312 |
104016 |
Аналог NOP |
314 |
10004 |
ОЗУП |
316 |
4766 |
ОЗУП |
322 |
42704 |
ОЗУП/РП |
326 |
20426 |
ОЗУП |
332 |
1002 |
ОЗУП |
334 |
4766 |
ОЗУП |
342 |
20426 |
ОЗУП |
346 |
103431 |
Примечание 4 |
350 |
1002 |
ОЗУП |
352 |
4766 |
ОЗУП |
360 |
20426 |
ОЗУП |
364 |
1006 |
ОЗУП |
366 |
5704 |
ОЗУП |
370 |
1002 |
ОЗУП |
372 |
16704 |
ОЗУП |
376 |
4714 |
ОЗУП |
ОЗУП - ОЗУ пользователя; ОЗУП/РП - ОЗУ экрана, используемое пользователем в режиме РП; текст-описание выполняемого действия;
Примечание 1: вызов следующей последовательности команд:
JSR R7,@#175732 RTS R7
Примечание 2:
BIC# 140000,R1 ADD @202, R1 JSR R7,@#104066 JSR R7, @#111616 JSR R7, @# 103222 RTS R7
Примечание 3:
JSR R7, @#111516 JSR R7, @#103222 RTS R7
Примечание 4:
JSR R7, @#104021 RTS R7
Некоторые EMT-функции имеют одинаковые адреса вызова, тогда для вызова подпрограммы можно пользоваться любой из них. Вызываемая подпрограмма должна начинаться с указанного адреса (причём первой должна быть записана исполняемая команда) и заканчиваться оператором RTS R7. О сохранности используемых регистров должен также позаботиться сам пользователь.
№№ EMT |
Адрес |
Прим. |
№№ EMT |
Адрес |
Прим. |
№№ EMT |
Адрес |
Прим. |
---|---|---|---|---|---|---|---|---|
0 |
166 |
С |
2 |
254 |
С |
116 |
2 |
В |
124 |
177400 |
Р |
136 |
2 |
В |
144 |
20 |
В |
152 |
77202 |
Э |
156 |
100442 |
Н |
160 |
4 |
В |
166 |
30 |
В |
172 |
200 |
С |
174 |
32 |
В |
200 |
120 |
С |
204 |
77202 |
Э |
206 |
104004 |
Н |
212 |
77746 |
Э |
216 |
77734 |
Э |
222 |
77770 |
Э |
226 |
77770 |
Э |
242 |
177714 |
Р |
246 |
220 |
С |
250 |
177716 |
Р |
252 |
106426 |
Н |
254 |
0 |
В |
256 |
206 |
С |
266 |
177650 |
Р |
276 |
177640 |
Р |
302 |
100720 |
Н |
306 |
150 |
С |
320 |
150 |
С |
324 |
240 |
С |
330 |
114 |
С |
336 |
176 |
С |
340 |
756 |
С |
344 |
114 |
С |
354 |
300 |
С |
356 |
750 |
С |
362 |
122 |
С |
374 |
77666 |
Э |
С - область стека; В - область векторов прерываний; Э - ОЗУ экрана даже в режиме РП; Р - область регистров; Н - неизвестный вход в ПЗУ (в Монитор, в Бейсик или в Фокал).
В принципе при особой необходимости программу пользователя можно с известными предосторожностями «втиснуть» и в область стека. Можно также разместить очень короткую подпрограммку или команду МР рядом или вместо вектора прерывания (если точно известно, что он не будет использован или если исхитриться «подгадать» адрес прерывания таким, чтобы он одновременно был и командой Ассемблера). Если же оперативной памяти «позарез» не хватает, можно рискнуть занять под размещаемые для временных вычислений блоки оставшийся экран. Во всех этих случаях можно пользоваться приведёнными в таблице 2 EMT-функциями.
Комментарием «Н» отмечены EMT-функции, результат исполнения которых мне не известен, хотя те, кто досконально знает транслятор БЕЙСИКа или ФОКАЛа или проведёт соответствующие исследования, может быть, найдут применение и им.
Заключение рецензента
В основном соображения, высказываемые Усенковым Д.Ю. о команде EMT, верные, но следует остановиться на нескольких моментах.
Во-первых, команда перехода к подпрограмме JSR не обязательно длиннее команды EMT! Это зависит от вида адресации. Например, вариант 4711 (JSR R7, @R1) занимает в памяти только два байта, но в этом случае адрес подпрограммы необходимо сформировать в R1.
Во-вторых, в предлагаемом материале есть неточности:
- в таблице 1 адреса входов подпрограмм должны быть равны: EMT 232 - 44748; EMT 214 - 1052668; EMT 346 - 1034308;
- адрес входа 1052668 указывает на несуществующую команду, а не на команду перехода к подпрограмме;
- подпрограмма для примечания 4 указана неточно, любители могут убедиться в этом сами, просмотрев область памяти, начиная с адреса 1034308;
- в таблице 2 для EMT 250 адрес равен 1777168.
Используя предлагаемые Усенковым возможности, можно достичь некоторой экономии программной памяти за счёт целенаправленного размещения часто применяемых подпрограмм с определённых адресов. Всё же этот способ нельзя рекомендовать для широкого использования вследствие возникающей непереносимости написанных таким образом программ на компьютеры с совместимой системой команд (например, БК0011).
Если же говорить об экономии памяти для программ, разрабатываемых на ассемблере (и на других языках), то экономию легче всего получить за счет тщательного выбора метода решения вставшей перед Вами задачи и осторожного выбора структуры данных.
Поверьте, затраченное на выбор метода и структуры данных время окупится при программировании более коротким кодом и, следовательно, меньшим временем на программирование и отладку.
Знайте, что если программа на ассемблере не умещается в 16Кб ОЗУ, значит, вы что-то не учли или эта программа не для БК0010.
Жариков Л. Н.