Исследование ИМС с помощью БК-0010.01
На некоторых специальностях Хабаровскою техникума железнодорожного транспорта изучается предмет «Основы вычислительной и микропроцессорной техники». Чтобы досконально усвоить логику работы ИМС, необходима отработка принципов их работы на макетах-тренажёрах.
Традиционный макет-тренажёр стандартен: это блок питания, индикаторы-светодиоды, элементы коммутации, генераторы, осциллограф. Изготовить такой макет трудно и дорого. Мы решили идти нетрадиционным путём.
Сначала разработали программы, позволяющие демонстрировать работу логических элементов И, ИЛИ, НЕ, ИЛИ-НЕ, И-НЕ. При изменении уровней входных сигналов заполняется таблица истинности, одновременно на экране вычерчивается временная диаграмма. Уязвимость способа в том, что нет навыка практической работы собственно с ИМС.
Освоив КУВТ-86, мы нашли иное решение этой задачи. Поясним на примере исследования ИМС счётчиков-делителей К155ИЕ2, ИЕ4, ИЕ5. Выполняется макет с коммутационными гнёздами и набором шаблонов, на которых изображены условные графические обозначения указанных ИМС (принципиальная схема - рис. 1).
Рис. 1
На макет с помощью разъёма можно установить любую ИМС. Питание ИМС обеспечивается от БК-0010. Управление работой ИМС осуществляется программно: микро-ЭВМ через порт ввода-вывода подаёт запускающие импульсы и анализирует состояние триггеров счётчика. Работа с программой сводится к нажатию клавиши ПРОБЕЛ, что имитирует подачу входного импульса и приводит к заполнению очередной строки таблицы истинности. Вид таблицы истинности зависит от того, какая коммутация произведена шнуровыми парами на макете (можно получить различные коэффициенты счета ИМС). При желании можно получить твёрдую копию таблицы. Пример - на рис. 2.
Таблица состояний |
||||
---|---|---|---|---|
Номер импульса |
Q1 |
Q2 |
Q3 |
Q4 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
0 |
0 |
2 |
0 |
1 |
0 |
0 |
3 |
1 |
1 |
0 |
0 |
4 |
0 |
0 |
1 |
0 |
5 |
1 |
0 |
1 |
0 |
6 |
0 |
1 |
1 |
0 |
7 |
1 |
1 |
1 |
0 |
8 |
0 |
0 |
0 |
1 |
9 |
1 |
0 |
0 |
1 |
10 |
0 |
1 |
0 |
1 |
11 |
1 |
1 |
0 |
1 |
12 |
0 |
0 |
1 |
1 |
13 |
1 |
0 |
1 |
1 |
14 |
0 |
1 |
1 |
1 |
15 |
1 |
1 |
1 |
1 |
16 |
0 |
0 |
0 |
0 |
Рис. 2
После заполнения таблицы истинности на экране строится временная диаграмма с требуемым коэффициентом пересчёта. Пример - на рис. 3.
Рис. 3
Перед началом работы с тренажёром учащемуся даётся задание получить для указанной ИМС временные диаграммы при нескольких коэффициентах деления.
Данная методика исследования ИМС не требует больших материальных затрат на остродефицитную измерительную технику, а по наглядности и простоте обращения с макетом, на наш взгляд, превосходит все известные нам методы.
Л. ПОПОВ, А. КОНДРАТЕНКО
Самомодифицирующиеся программы
- Полезными являются только четыре режима адресации, использующие программный счётчик (PC) в качестве регистра, а именно: 27 (непосредственный), 37 (абсолютный), 67 (относительный), 77 (косвенно-относительный ).
- После изменения программы требуется её перекомпиляция.
- Доступ к ячейкам, содержащим команды, должен быть разрешён только по чтению.
Эти и другие незыблемые правила работы в системе PDP-11, в качестве аналога которой можно рассматривать БК-0010, на самом деле являются достаточно спорными. Их нарушение даёт порой новые ценные возможности.
Для начала кратко рассмотрим способы адресации, обратив внимание на некоторые известные вещи.
Регистровый (0) и косвенно-регистровый (1) режимы достаточно тривиальны.
Автоинкрементный (2) и автодекрементный (4) позволяют работать с массивами данных: чисел, кодов символов и т.д. Для этого нужно записать в один из регистров (Rk) адрес первого элемента массива (или следующего за последним) и в цикле обработать весь массив, обращаясь к элементу (Rk)+ или -(Rk).
Косвенно-автоинкрементный (3) и косвенно-автодекрементный (5) режимы позволяют работать с массивами адресов. Обработка массива аналогична предыдущему, а вот что такое массив адресов, разберём подробнее.
Смысл этих адресаций в том, что значение из очередной ячейки массива используется как адрес ячейки, с которой работает команда. В массиве адресов можно записать последовательно адреса регистров внешних устройств (для последовательного обращения к ним), адреса конкретных данных (заранее записанные, случайные или введённые с клавиатуры) и т.д. Не исключается также повторение адресов.
Что касается индексного (6) и косвенно-индексного (7) режимов, они позволяют обращаться к элементу массива данных (или адресов) по его номеру, если адрес начального элемента записать в регистр, а номер (для слов - удвоенный номер) - в ячейку для индекса. Отметим, что индекс (номер) записывается в отдельную ячейку, следующую за командой. К этому очень важному замечанию мы ещё вернёмся.
Непосредственный (27) режим позволяет записывать значение в ячейку, следующую за командой (например, для начального присваивания). Абсолютный (37) режим задаёт адрес для обработки, например, адрес регистра внешнего устройства.
Адресации относительная (67) и косвенно-относительная (77) позволяют перемещать программу без дополнительной подстройки адресов, так как используют разность адресов (смещение) команды и ячейки, с которой работает команда или в которой находится адрес рабочей ячейки. Здесь также следует отметить, что смещение записывается в отдельной ячейке.
Из оставшихся четырёх режимов остановимся подробно на 07 и 17 (47 и 57 действительно бесполезны).
Режим 07 рассмотрим на примере команд MOV и ADD. Если PC используется в качестве источника, то, например, команда MOV PC,DD (DD - приёмник) позволит запомнить адрес следующей ячейки в приёмнике. Это полезно при работе с подпрограммами, но команда JSR более эффективна. Команда ADD PC,DD и вовсе бесполезна. Если же PC - приёмник, то получим следующее. MOV SS,PC (SS - источник) приведёт к замене значения счётчика команд на значение источника, что равносильно безусловному переходу по абсолютному адресу. ADD SS,PC увеличит значение PC на значение источника, т.е. источник сыграет роль смещения аналогично командам BR, BEQ и т.д. Но здесь смещение не ограничивается одним байтом, что делает эту команду полезной в случаях, когда большое смещение не позволяет использовать команды BR, BEQ и др. Пусть нужно написать команду «если равно 0, то на 530(8) слов». Так как 530(8)>377(8), то BEQ использовать нельзя. Придётся действовать так:
BNE А 001002 ADD #1260,PC 012707 001260 А: продолжение ......
Замечание: 1260(8)=2*530(8). Смещение задаётся в байтах.
Таким образом, адресация 07 не так уж бесполезна.
Займёмся теперь адресацией 17, ради которой и написана статья.
Рассмотрим команду MOV (PC),DD. При её выполнении процессор:
- скопирует в приёмник значение из следующей после команды ячейки (в момент выполнения в PC содержится её адрес);
- перейдёт к чтению следующей команды;
- так как в PC находится адрес ячейки, которая была источником, то её значение и воспримет процессор как очередную команду.
Вот тут и возникает противоречие: содержимое ячейки должно быть, с одной стороны, значением, а с другой - командой. Трудно не согласиться с Т.С. Фрэнком, когда он в своей книге «PDP-11. Архитектура и программирование», отказав адресации 17 в практичности, переходит к адресации 27, при которой после прочтения значения PC снова увеличивается на 2 и указывает на следующую ячейку, уже с командой.
Зато случай MOV SS,(PC) предоставляет новые возможности, на которые не обратил внимания даже Т.С. Фрэнк. Проследим за выполнением этой команды:
- процессор скопирует содержимое источника в следующую после команды ячейку (аналогично предыдущему случаю);
- перейдёт к чтению следующей команды;
- прочтёт только что записанное как команду.
Сразу возникают вопросы: зачем записывать команду в ячейку перед её выполнением, затратив при этом ещё команду, если можно было записать её туда в процессе создания программы? Как быть с той информацией, которая была в ячейке ранее? Где гарантия, что значением источника будет код нужной команды? Что, кроме неприятностей, принесёт изменение команд программы в процессе выполнения?
Отвечать будем на все вопросы сразу. Если таким способом записанная команда выполняется один раз, то этот приём бесполезен. Если же выполнение будет многократным (цикл, подпрограмма и др.), то можно ожидать полезных эффектов, если записываться будут разные команды.
Простой пример. Пусть в источнике используется автоинкрементная адресация с регистром Rk ; тогда команда MOV (Rk)+,(PC) при каждом проходе цикла запишет в следующую ячейку очередной элемент массива, начальный адрес которого предварительно был записан в Rk. Этот массив логично назвать массивом команд, так как очередной его элемент будет выполняться как команда при очередном проходе цикла. Таким образом, этот приём позволяет использовать циклы с меняющимися командами.
Пример более сложный. В компьютере БК-0010 используются 15 различных режимов работы дисплея. С помощью команды ЕМТ 34 можно определить ССД (слово состояния дисплея), в котором отражены текущие режимы. Поскольку для каждой программы нужны свои режимы, требуется установить их.
Допустим, необходимо установить режимы (если они сброшены) 32 символа в строке (0-й бит), русский регистр (3-й бит), подчёркивание символа (4-й бит), гашение курсора (14-й бит); сбросить режимы (если они установлены) инверсия фона (1-й бит), расширенная память (2-й бит), инверсия символа (5-й бит), индикация СУ (6-й бит), блокировка редактирования (7-й бит), ГРАФ (8-й бит); не изменять остальные режимы (несущественные).
Алгоритм достаточно прост: проверяем наличие (отсутствие) существенного режима и, если нужно сбросить (установить) его, передаём монитору код изменения данного режима с помощью команды ЕМТ 16. Реализовать его можно разными способами:
- для каждого существенного режима написать команды проверки и изменения (без цикла);
- написать цикл для установки и цикл для сбрасывания режимов;
- написать один цикл для всех режимов, используя адресацию 17.
Покажем решение третьим способом.
EMT 34 104034 ;SSD в R0 MOV R0,R1 010001 ;R0 в R1 MOV #1,R2 012702 ;Маска в R2 000001 ;Начальная ; маска = 1 MOV #AKOD,R3 012703 ; AKOD ;Адрес ; массива кодов смены режима MOV #АКОМ,R4 012704 ; АКОМ ;Адрес ; массива команд MOV #17,R5 012705 ; 000017 ;К-во ; повторений цикла ; начало цикла ; A: MOVB (R3)+,R0 112300 ;Очередной ; код изменения режима в R0 MOV (R4)+,(PC) 012417 ;Очередную ; команду в следующую ячейку NOP 000240 ;..команда.. BIT R2,R1 010201 ;Проверка ; очередного режима BEQ В 001401 ;Проверка ; на изменение режима ЕМТ 16 104016 ;Изменение ; очередного режима В: ASL R2 006302 ;Очередная ; маска SOB R5,A 077510 ; ; конец цикла Массив кодов Байты Слова 235 233 116633 016 214 007214 234 237 116237 204 202 102202 226 225 113225 000 227 000227 000 000 000000 000 232 000232 Массив команд XOR R2,R1 074201 NOP 000240 NOP 000240 XOR R2,R1 074201 XOR R2,R1 074201 NOP 000240 NOP 000240 NOP 000240 NOP 000240 BR В 000403 BR В 000403 BR В 000403 BR В 000403 BR В 000403 XOR R2,R1 074201
Рассмотрим работу программы с массивом команд. В нём только три различные команды; их порядок зависит лишь от того, какие режимы нам нужны, и может быть произвольным. Команда NOP соответствует случаю, когда режим не нужен: последующие команды сбросят данный режим, если он установлен (ЕМТ 16), и не будут изменять, если сброшен (BEQ В). Команда XOR R2,R1 (случай нужного режима) изменяет в R1 значение очередного бита на противоположное (R2 - текущая маска), в результате чего последующие команды будут действовать наоборот: установят данный режим, если сброшен (ЕМТ 16), иначе оставят (BEQ В). В случае несущественных режимов используется команда BR В, которая позволяет сразу перейти к следующей маске и следующему режиму.
Мы получили программу, постоянно изменяющуюся в процессе работы. При этом экономится память и немного замедляется выполнение (так же, как и при замене циклом одинаковых команд)
Такая подстановка возможна только для однословных команд. В других случаях можно применить адресацию 67, позволяющую менять содержимое ячейки заранее, а не непосредственно перед выполнением. Можно также менять индекс в индексной адресации (он находится в отдельной ячейке).
Пример 1.
MOV #ADR,R1 012701 ADR ;Начальный ; адрес массива A: .......................... ;Расчет ; индекса MOV SS,B 01SS67 ;3апись ; индекса ...... ;Смещение ADD 0(R1),DD 0667DD ;Работа ; с конкретным элементом ; массива В: 000000 ;Индекс ; (меняется при записи) .......................... BEQ А ...... ;Варианты: ; BNE,SOB,...
Пример 2. Пусть при каждом проходе цикла подставляются команды разной длины:
MOV А, В 016767 ...... ;Смещение ; к А ...... ;Смещение ; к B MOV @#177662,R4 013704 ;Чтение 177662 ;кода из ; регистра данных клавиатуры ADD R5,R2 060502 NOP 000240
Решение.
MOV #ADR,R1 012701 ADR ;Начальный ; адрес массива команд А: .......................... ;Начало ; цикла MOV (R1)+,B 012167 ...... ;Смещение ; к В MOV (R1)+,C 012167 ...... ;Смешение ; к C MOV (R1)+,D 012167 ...... ;Смещение ; к D В: 000000 ;Три ячейки С: 000000 ;для под- D: 000000 ;становки ; команды BЕQ А ;Варианты: ; BNE, SOB, ... Массив команд (цифровые метки указывают номера команд и в программе не нужны) 1: MOV А,В 016767 ...... ; Смещение ; к А ...... ; Смещение ; к B 2: MOV @#177662,R4 013704 ;Чтение 177662 ;кода из ; регистра данных клавиатуры NOP 000240 3: ADD R5,R2 060502 NOP 000240 ;Вариант: ; BR+1 000401 NOP 000240 4: NOP 000240 ;Вариант: ; BR+2 000402 NOP 000240 NOP 000240 5: .......................... ;Далее ; аналогично
Этим, конечно, не исчерпываются возможности применения необычных адресаций и программ-хамелеонов, но в небольшой статье описать все случаи невозможно.
Ю. ГИМАТОВ
Обработка прерываний по клавише СТОП средствами Бейсика
Изменение действия клавиши СТОП - приём, широко используемый при программировании в машинных кодах. Реализация его проста: адрес обработки прерывания по клавише СТОП (он хранится в ячейке 4) заменяется на какой-либо другой (например, начала программы пользователя или её фрагмента).
Как оказалось, Бейсику тоже вполне по силам «приручить» клавишу СТОП. Теоретические предпосылки взяты из статьи А. и В. Авсеевых «Особенности транслятора с языка Бейсик для БК-0010-01» (ИНФО. 1990. № 2.), которым автор выражает огромную благодарность за их замечательную работу, и сводятся к следующему.
Исполняемая Бейсик-программа хранится в памяти БК в виде «шитого кода» - последовательности адресов подпрограмм ПЗУ, реализующих команды Бейсика, и необходимых для работы этих подпрограмм данных. Начальный адрес расположения «шитого кода» задаётся чётным числом, равным или превышающим на 1 хранящееся в ячейке 1026[*] (т.е. его можно определить как РЕЕК (1026%)+РЕЕК(1026%)MOD2%). Управление от одной подпрограммы к другой передаётся через регистр R4: в конце каждой подпрограммы ПЗУ стоит команда JMP @(R4)+, т.е. в R4 находится адрес, адреса следующей подпрограммы. Изменив содержимое R4 в процессе выполнения Бейсик-программы, мы тем самым изменим порядок её выполнения.
Пусть, например, надо, чтобы при нажатии на СТОП Бейсик-программа начинала работу с самого начала. Из сказанного ясно, что для этого следствием нажатия на клавишу СТОП должны быть засылка в R4 адреса начала «шитого кода» программы и выполнение команды JMP @(R4)+, что обеспечивается добавлением в начало программы четырех строк:
10 POKE 512%,5572% 'код команды MOV (PC)+,R4 20 POKE 514%,PEEK(1026%)+PEEK(1026%)MOD2% 'адрес адреса начала 30 POKE 516%,92% 'код команды JMP @(R4)+ 40 POKE 4%,512% 'новый адрес обработки прерывания
А если при нажатии на клавишу СТОП должен произойти переход не к началу программы, а к какому-то её фрагменту?
Оставим в начале программы те же четыре строки, слегка изменив строку 20:
20 POKE 514%,1000%
Число 1000 в ней ничего не значит - оно просто резервирует место для адреса начала фрагмента, который мы ещё не знаем. Чтобы узнать его, пометим начало нашего фрагмента каким-либо характерным числом, которое мы сможем легко найти, анализируя содержимое ОЗУ; адрес, следующий за адресом этого числа, и будет искомым.
В качестве маркеров удобно использовать операторы END, STOP, ВЕЕР, CLS, CLOSE («шитый код» соответственно -9774, -9748, -8718, -8706, -6738).
Расположим после нашей программы строки, определяющие адрес маркера:
10000 FOR J%=1500%TO16382%ST2% 'просмотр памяти от 1500 до конца ОЗУ 10010 IF PEEK(J%)=-9774%TH?J% 'маркером выбран END 10020 NEXT J%
Выполним их.
RUN 10000
В результате может получиться довольно внушительная цепочка адресов, среди которых выделить нужный нелегко. Поэтому пометим начало нашего фрагмента не одним, а тремя одинаковыми маркерами (в данном случае - тремя операторами END, идущими подряд). Теперь, увидев в цепочке адресов три последовательных числа, можно смело сказать, что нужный адрес найден.
Но это ещё не всё. Нехорошо оставлять программу, «засорённую» вспомогательными элементами, поэтому удалим все три маркера и строки 10000-10020, предварительно запомнив адрес первого из маркеров (меньшее из трёх последовательных чисел) и посмотрев содержимое ячейки 1026.
После удаления «мусора» произведём «утряску» программы командой REN и вновь посмотрим содержимое ячейки 1026. Там будет число меньше предыдущего. Их разность даст «поправку на удаление»; вычтя её из первого маркера, получим нужный адрес. Осталось занести его в строку 20 вместо числа 1000, вызвав её на редактирование командой .20.
При изменении длины программы происходит смещение «шитого кода» в памяти, поэтому перечисленные действия надо производить с уже отлаженной программой.
Рассмотрим пример. Текст программы:
10 POKE 512%,5572% 20 POKE 514%,1000% 30 POKE 516%,92% 40 POKE 4%,512% 50 CLS 60 ?"A"; 70 J%=J%+1% 80 GOТO 60 81 END 82 END 83 END 90 CLS 100 ?"Выдано"J%"’А’" 110 РОКЕ 4%,-24420% 120 END 10000 FOR J%=1500%TO16382%ST2% 10010 IF PEEK(J%)=-9774%TH?J% 10020 NEXT J%
Найдём адрес фрагмента, записанного в строках 90-120:
RUN 10000 1798 1800 1802 1842 1900
Нужное нам число - 1798.
?РЕЕК(1026) 1730 DEL 81-83 DEL 10000- REN ?PEEK(1026) 1676 ?1798-(1730-1676) 1744
Нашли адрес, помещаем его в строку 20:
.20 20 POKE 514%,1000% 20 POKE 514%,1744%
Окончательный вид программы:
10 POKE 512%,5572% 20 POKE 514%,1744% 30 POKE 516%,92% 40 POKE 4%,512% 50 CLS 60 ?"A"; 70 J%=J%+1% 80 GOTO 60 90 CLS 100 ?"Выдано"J%"'A'" 110 POKE 4%,-24420% 120 END
Д. ЯКОШВИЛИ
Москва
[*] Здесь и далее все числа даны в десятичной системе счисления.
Псевдопараллельное исполнение программ на БК-0010
Используя возможность прерывания после каждой команды, если установлен бит Т слова состояния процессора, можно исполнять несколько кодовых программ «параллельно», когда после исполнения нескольких команд одной программы исполняются несколько команд второй, затем третьей и т.д. Так как время исполнения небольшого числа команд процессора достаточно мало, то подобный приём даёт эффект почти такой же, как если бы использовалось несколько менее мощных, чем реальный, процессоров.
Расскажем об этом методе подробнее.
Слово состояния процессора (PSW) БК-0010 имеет адрес 177776. Его младший байт выглядит так:
177776: |
P |
P |
P |
T |
N |
Z |
V |
C |
Для нас сейчас важен бит Т. Обычно он равен 0, если же в нём записана единица, то после исполнения каждой команды происходит прерывание по вектору 14, т.е. выполняются следующие команды:
MOV @#177776,-(SP) MOV PC,-(SP) MOV @#14,PC MOV @#16,@#177776
После этого можно совершить какие-то действия и возвратить управление основной программе командой RTT, которая выполняет следующие действия:
MOV (SP)+,PC MOV (SP)+,@#177776
Исполнится следующая команда основной программы, после чего снова возникнет прерывание по вектору 14 и т.д.
Установку бита Т в 1 обычно используют для пошагового исполнения кодовых программ при отладке. Мы же используем этот приём для организации «параллельного» исполнения программ, например, так.
Поместим в ОЗУ N программ и N специальных мониторов, работающих следующим образом. В момент работы первой программы бит Т=1, @#14=<адрес начала первого монитора>. После исполнения одной команды первой программы произойдёт прерывание и управление перейдёт к первому монитору, который сохранит значения регистров R0-R5, PC и PSW, а затем активизирует данные, необходимые для исполнения второй программы: зашлёт в регистры процессора значения, нужные второй программе, в стек - соответствующие ей значения PC и PSW, а в @#14-адрес начала второго монитора. После этого выполняется команда RTT, возвращающая управление, но уже не первой, а второй программе, поскольку значение PC в стеке было подменено монитором.
Второй монитор аналогично сохраняет регистры второй программы, а восстанавливает регистры третьей и т. д, вплоть до N-го монитора, который сохраняет регистры своей программы, а восстанавливает регистры первой и засылает в @#14 адрес первого монитора.
В результате в N основных программах выполнится по одной команде, причём каждая выполнится так, как если бы других программ не было (не считая уменьшения быстродействия и ресурсов памяти).
Но быстродействие нужно всё же посчитать. Сравним «сольное» исполнение программы и «параллельное» вместе с другими N-1 программам. Пусть время выполнения любой команды равно t. Тогда в первом случае на одну команду тратится время t, а во втором - не менее tN+ktN, где k - число команд в мониторе. Следовательно, происходит замедление по крайней мере в N(k+1) раз.
В испытываемых мониторах было 18 команд, замедление при работе двух программ было в 38 раз, не считая времени на операции по прерыванию.
Чтобы ослабить этот эффект, можно выполнять из каждой программы не одну команду, а серию из S команд, в течение которой дополнительное время уходит лишь на приращение счётчика серии, проверку его и команду RТТ (обозначим число этих дополнительных команд k1). Теперь время исполнения S команд каждой из N программ равно N(S+k1)t+N(k+1)t (к k добавляется единица, потому что при передаче управления другому монитору надо снова выставить счётчик).
Итак, при исполнении S команд каждой из N программ по одной тратится время, равное tSN(k+1), а при исполнении сериями по S команд - tN(S+k1+k+1). В первом случае общее время превосходит полезное (tSN) в k+1 раз, во втором - в (S+k1+k+1)/S раз.
При k=18, k1=3, S=22 в первом случае превышение реального времени над полезным в 19 раз, во втором - в 2 раза.
Рассмотрим реализацию этого алгоритма на БК-0010.
; 10-Jan-91 ; Монитор для параллельного исполнения ; двух программ START: MOV #VEC,R1 ;Пусковая инициализация MOV #5,R0 1: MOV #20,@(R1)+ SOB R0,1 MOV #100274,@#4 ;По стопу CLR @#6 MOV #INT1,@#14 ;По Т-разряду CLR @#16 MOV #20,-(SP) ;ССП для 1-й программы MOV #20,PSR2 ;ССП для 2-й программы MOV #10000,-(SP) ;Стартовый адрес ; для 1-й программы MOV #17000,PC2 ;Стартовый адрес ; для 2-й программы RTT VEC: .#12.#22.#26.#32.#36 INT1: DEC COUNT ;Прерывание 1-й BNE 1 ; программы MOV #30,COUNT MOV (SP)+,PC1 MOV (SP)+,PSR1 MOV R0,R01 MOV R1,R11 MOV R2,R21 MOV R3,R31 MOV R4,R41 MOV R5,R51 MOV R02,R0 MOV R12,R1 MOV R22,R2 MOV R32,R3 MOV R42,R4 MOV R52,R5 MOV PSR2,-(SP) MOV PC2,-(SP) MOV #INT2,@#14 1: RTT INT2: DEC COUNT ;Прерывание 2-й BNE 1 ; программы MOV #30,COUNT MOV (SP)+ ,PC2 MOV (SP)+,PSR2 MOV R0,R02 MOV R1,R12 MOV R2,R22 MOV R3,R32 MOV R4,R42 MOV R5,R52 MOV R01,R0 MOV R11,R1 MOV R21,R2 MOV R31,R3 MOV R41,R4 MOV R51,R5 MOV PSR1,-(SP) MOV PC1,-(SP) MOV #INT1,@#14 1: RTT PC1: .#0 ;Состояние 1-й PSR1: .#0 ; программы R01: .#0 R11: .#0 R21: .#0 R31: .#0 R41: .#0 R51: .#0 РС2: .#0 ;Состояние 2-й PSR2: .#0 ; программы R02: .#0 R12: .#0 R22: .#0 R32: .#0 R42: .#0 R52: .#0 COUNT: .#30 ;Размер серии команд END
Рассматривался случаи работы 2 программ, соответственно вспомогательная программа состояла из 3 частей: стартовой части и двух мониторов.
Стартовая часть (метка START) предназначена для установки векторов прерываний (вернее, их вторых слов) по Т-разряду, СТОПу, резервному коду, команде IOT, аварии питания, командам ЕМТ и TRAP. Кроме того, устанавливается холодный запуск монитора по нажатию СТОП и заносится адрес первого монитора (INT1) в @#14, а также заполняются начальные PC и PSW двух программ. Затем управление передаётся первой команде с одновременной установкой Т-бита с помощью команды RTT.
Программы исполняются сериями по 30 команд. Это реализуется с помощью ячейки COUNT. Мониторы INT1 и INT2 используют ячейки РС1-2, PSR1-2, R01 - R51, R02-R52 для хранения состояний программ 1 и 2. Программа написана на ассемблере МИКРО1103Б и не претендует на оптимальность - главным было продемонстрировать идеи метода.
Толчком к применению изложенного подхода было желание озвучивать программы, т.е. добиться параллельно исполнения программы, например, игры и программы, исполняющей мелодию. В экспериментах в качестве основной бралась программка, опрашивающая регистр 177716 и при выявлении нажатии клавиши печатающая код из @#177662. При S=64 и более (до 512) удавалось получить вполне приемлемое звучание, правда при уменьшении количества итераций в циклах типа SOB (они применяются в подпрограммах, генерируемых МЕЛОМАНом) в 2-10 раз.
При большом размере серий начинает чувствоваться прерывистость в работе. Кроме того, поскольку время исполнения разных команд разное, это сказывается на звучании.
Другие возможные области применения: синтез на БК многоголосой музыки, т.е. одновременное исполнение нескольких музыкальных программ;
- в играх одна из программ может заниматься обслуживанием героя игры, другая - создавать игровой фон, обслуживая другие объекты;
- если в игре участвуют двое, то одна программа может обслуживать одного игрока, вторая - другого, а третья - создавать фон;
- в системных программах одна из программ может обслуживать внутренний таймер.
В. БУЛИТКО
Подключение блока клавиатуры МС 7008.01 к БК
На прилавках магазинов «Электроника» недавно появились блоки клавиатуры «Электроника МС 7008.01», практически лишённые тех недостатков, которые столько лет досаждали пользователям БК. Новая клавиатура имеет очень лёгкий ход, избавлена от дребезга клавиш и с минимальными усилиями может быть встроена в уже имеющийся корпус ПЭВМ.
Технические характеристики клавиатуры:
мощность коммутируемого сигнала 10-2 ВА;
количество клавиш - 74;
наработка на отказ - 2x106 циклов;
усилие нажатия - 1,2 Н;
ход клавиши 3,5-4,5 мм;
частота нажатий на клавишу - 10 Гц.
Проще всего подключить новый блок клавиатуры к плате вычислителя БК, отрезав от старой клавиатуры два шлейфа проводников с вилками ХТ1 и ХТ2 и под паяв их к разъёмам блока в соответствии с приводимой таблицей.
Оставшийся на старой клавиатуре пьезодинамик следует осторожно выпаять и подсоединить к контактам 7 и 5 разъёма ХТ2 МС 7008.01.
Разъём XT1 МС 7008.01 |
Разъёмы шлейфов |
Разъём XT2 МС 7008.01 |
Разъёмы шлейфов |
Разъём XT3 МС 7008.01 |
Разъёмы шлейфов |
---|---|---|---|---|---|
1 |
XT2:15 |
1 |
- |
1 |
- |
2 |
XT1:1 |
2 |
XT2:9 |
2 |
XT1:15 |
3 |
XT1:2 |
3 |
XT2:10 |
3 |
XT2:11 |
4 |
XT1:3 |
4 |
XT2:14 |
4 |
XT2:1 |
3 |
XT1:5 |
5 |
XT2:8 |
5 |
XT1:14 |
4 |
XT1:6 |
6 |
XT2:4 |
6 |
XT1:13 |
7 |
XT1:11 |
7 |
XT2:5 |
|
|
8 |
XT1:7 |
8 |
XT2:2 |
|
|
9 |
XT1:9 |
9 |
XT2:3 |
|
|
10 |
XT1:10 |
10 |
XT2:7 |
|
|
11 |
XT1:4 |
11 |
XT2:6 |
|
|
12 |
XT1:8 |
12 |
- |
|
|
Компактность и конструктивная простота МС 7008.01 позволяет использовать его в качестве дополнительной (выносной) клавиатуры; правда, при этом приходится решать две новые проблемы - где достать достаточно гибкий и лёгкий 27-жильный соединительный шлейф и как сделать корпус, но зато сколько удобств появляется потом!
И. ПАНЧЕНКОВ
Параллельные процессы на БК-0010
Нередко бывает желательно, чтобы во время выполнения программы играла музыка или, к примеру, мигал курсор. Этого можно добиться, вставив после каждых 100 команд команду TRAP с аргументом, соответствующим высоте звука для случая с мелодией, и написав соответствующую программу обработки прерывания по вектору 34.
Однако так невозможно добиться, например, мигания курсора во время выполнения системных ЕМТ-подпрограмм. Преодолеть это ограничение можно, используя прерывание по вектору 14 и внутренний таймер БК, подробно описанный в «ИНФО»1-90.
Вот пример подпрограммы, заставляющей мигать курсор, в том числе и во время выполнения ЕМТ 6 (во время остальных ЕМТ мигание прекращается).
;Текст программы пригоден для систем МИКРО10 и ; старше. В случае использования более ранних ; версий вводите только три первые буквы имен ; меток и констант PERIOD=177706 DATA=177710 UPR=177712 PUSK=160 ;*** Инициализатор *** START: MOV #1000,@#PERIOD ;Занесение периода в ; регистр MOV #PUSK,@#UPR ;Запуск таймера MOV #BEGIN,@#14 ;Занесение адреса ; п/п обработки BIS #20,@#6 ;Установить Т-разряд BIS #20,@#12 ; для всех прерываний BIS #20,@#36 MOV @#30,SAVEMT ;Сохранить старый ; вектор ЕМТ MOV #EMT,@#30 ;Активизировать ; ЕМТ-диспетчер BPT ;Выполнить п/п ; обработки JMP @#100400 ;Выход в пусковой ; монитор ;*** П/п обработки прерывания *** BEGIN: CMP @#DATA,#600 ;Прошло ли время? BPL RET ;Нет - продолжить ; работу MOV @#32,-(SP) ;Сохранить ССП BIC #20,@#32 ;Очистка Т-бита MOV R0,-(SP) ;Сохранить R0 MOV #232,R0 ;инвертировать курсор EMT 16 MOV (SP)+,R0 ;Восстановить R0 MOV (SP)+,@#32 ;Восстановить ССП MOV #PUSK,@#UPR ;Сброс и запуск ; таймера RET: BIS #20,2(SP) ;Установить Т-бит RTT ;Возврат из ; прерывания ;*** Диспетчер ЕМТ *** EMT: MOV R5,-(SP) ;Сохранить R5 MOV 2(SP),R5 ;(Адрес ЕМТ)+2 - в R5 MOV -(R5),CMD ;ЕМТ - в ячейку CMD MOV (SP)+,R5 ;Восстановить R5 MOV SAVEMT,@#30 ;Восстановить ; вектор 30 CMP CMD,#104006 ;Это ЕМТ 6? BNE CMD ;Нет - выполнить BIS #20,@#32 ;Разрешить прерывав. ; по Т-биту CMD: NOP ;Выполнить ЕМТ MOV #ЕМТ,@#30 ;Адрес диспетчера ; - в 30 BIC #20,@#32 ;Запретить прерывая. ; по Т-биту RTT ;Возврат SAVEMT: .#0 ;Область для ;сохранения вектора 30 ЕND
Программа состоит из трёх частей: инициализатора, диспетчера ЕМТ и собственно подпрограммы обработки прерывания. Инициализатор выполняет начальный запуск таймера, сохранение вектора прерывания по ЕМТ, занесение адреса диспетчера ЕМТ в соответствующий вектор и установку Т-битов в ССП всех векторов прерываний. Диспетчер ЕМТ разрешает отладочное прерывание только на время работы ЕМТ 6 (это необходимо для нормальной работы с магнитофоном). Подпрограмма обработки прерывания по вектору 14 определяет, прошло ли необходимое время, и если да, то выдаёт команду на инвертирование курсора.
В случае использования данной подпрограммы в программе, не использующей запросы ЕМТ или самостоятельно запрещающей прерывание по вектору 14 на время их выполнения, диспетчер ЕМТ и соответствующие команды в инициализаторе можно удалить.
К сожалению, на некоторых БК внутренний таймер неисправен, поэтому приходится прибегать к различным ухищрениям. К примеру, можно подсчитывать число выполненных машинных команд и при достижении им определённого значения выполнять необходимые действия.
На основе системного таймера и прерывания по вектору 14 автором разработана программа МУЗОН, после компоновки с музыкальной подпрограммой редактора МЕЛОМАН 2 образующая перемещаемый блок исполнения мелодии параллельно выполнению основной программы. Существует версия МУЗОН: и с подсчётом числа выполненных команд.
Теоретически возможно распараллеливание до 5 процессов, но реально уже при 3 процессах работа значительно замедляется.
Автор благодарен Шишкину, автору игры KING’S VALLEY, а также авторам игры DIGGER за идею параллельного выполнения различных процессов.
Все заинтересовавшиеся данной темой, а также желающие получить МУЗОН могут написать по адресу: 241047, Брянск-47, а/я 109, брянский клуб пользователей БК.
Р. АСКЕРОВ