Решил немного поворчать на тему программ, работающих с терминалом напрямую через регистры (надо же чем-то заняться пока пиво пьется). Неработающие подобные проги доставали еще в начале 80ых, а сейчас и подавно. Речь идет о том, что многие программеры считали, что достаточно сделать в программе
как наступает чудо: программа может работать с терминалом на уровне регистров, а система при этом под ногами не путается. К сожалению это далеко не всегда верно. А посему немного расскажу о том как писать программы, чтобы они работали вообще в любом случае - вдруг современные программеры RT-11 (гы) будут писать правильноКод:CLR @#177560
Для начала перечислю случаи когда вышеописанная методика не работает (экзотические случаи вроде DEC Pro не рассматриваем):
- Первый случай очевиден: когда консольный регистр не 177560. Случай не частый, но тем не менее ничего невозможного в нем нет.
- Система многотерминальная. Тут целых две проблемы: во-первых консольный терминал может быть любым из сконфигуренных в системе; во-вторых при поддержке таймаута терминалов система постоянно приводит терминалы в порядок (в том числе заботится, чтобы прерывания от клавиатуры были разрешены)
Небольшой кусок кода в программе легко справляется со всем этим и делает программу рабочей в любой системе (здесь не рассматриваются хитрости которые зависят от конкретной версии или сборки монитора - только универсальный способ).
Для начала определения используемых смещений и битов.
Не касается терминалов напрямую, но... Совсем не помешает в начале программы следующий кусок (который к тому же места не занимает):Код:$JSX = 4 ;РАСШИРЕНОЕ СЛОВО СОСТОЯНИЯ ЗАДАНИЯ NOVBG$ = 100 ;БИТ ЗАПРЕТА VBGEXE $SYPTR = 54 ;УКАЗАТЕЛЬ НА ДАНЫЕ RMON $SYSGE = 372 ;ПАРАМЕТРЫ ГЕНЕРАЦИИ СИСТЕМЫ (RMON) MTTY$ = 20000 ;БИТ ПОДДЕРЖКИ МНОГОТЕРМИНАЛЬНОСТИ TSXP$ = 100000 ;БИТ TSX-PLUS $TTKS = 304 ;АДРЕС CSR КЛАВИАТУРЫ $CNTXT = 320 ;АДРЕС БЛОКА ОПИСАНИЯ ТЕКУЩЕГО ЗАДАНИЯ I.CNSL = 16 ;УКАЗАТЕЛЬ НА TCB ТЕРМИНАЛА ЗАДАНИЯ T.STAT = 14 ;СЛОВО СОСТОЯНИЯ ТЕРМИНАЛА T.CSR = 16 ;CSR ТЕРМИНАЛА DH11$ = 20000 ;ТЕРМИНАЛ НА DH-11 МУЛЬТИПЛЕКСОРЕ DZ11$ = 10000 ;ТЕРМИНАЛ НА DZ-11 МУЛЬТИПЛЕКСОРЕ
Этим мы добиваемся того, что в RT-11 V5.x программа не будет запускаться через VBGEXE. Потому как если запускать ее через VBGEXE, программа просто не увидит страницу ввода/вывода (на самом деле можно установить другой битик чтобы программа видела страницу ввода-вывода из под VBGEXE, но лучше таким баловством не заниматься).Код:.ASECT .=$JSX .WORD NOVBG$ .PSECT
Вот собственно и все. Мы получили прогу которая работает при нестандартном CSR, а также работает с правильным терминалом независимо от SET TT CONSOL=n, и система-вредитель нам не мешает!Код:START: MOV @#$SYPTR,R0 ;ПОЛУЧАЕМ АДРЕС СЕКЦИИ ДАННЫХ RMON TST $SYSGE(R0) ;ЭТО TSX-PLUS (ПОМНИМ: TSXP$ = 100000)? BMI TSX ;MI -> ДА. ВСЕ СОБСТВЕННО... BIT #MTTY$,$SYSGE(R0) ;МНОГОТЕРМИНАЛЬНАЯ СИСТЕМА? BEQ 10$ ;EQ -> НЕТ ;ЕСЛИ СИСТЕМА МНОГОТЕРМИНАЛЬНАЯ, СМЕЩЕНИЯ $TTKS, $TTKB, $TTPS И $TTPB ;НЕ ИСПОЛЬЗУЮТСЯ В ПРИНЦИПЕ, ДА И САМ ТЕРМИНАЛ МОЖЕТ БЫТЬ ВЫБРАН ЛЮБОЙ. ;НАША ЗАДАЧА - ПРОВЕРИТЬ, ЧТО ТЕКУЩИЙ ТЕРМИНАЛ - DL11 (ИНАЧЕ МЕТОД ;РАБОТЫ С РЕГИСТРАМИ СОВЕРШЕННО ДРУГОЙ), УЗНАТЬ CSR АДРЕС ТЕРМИНАЛА ;И СКАЗАТЬ СИСТЕМЕ, ЧТОБЫ НЕ МЕШАЛАСЬ. MOV $CNTXT(R0),R0 ;ПОЛУЧАЕМ АДРЕС БЛОКА ОПИСАНИЯ ЗАДАНИЯ MOV I.CNSL(R0),R0 ;ПОЛУЧАЕМ АДРЕС TCB ТЕРМИНАЛА BIT #DH11$!DZ11$,T.STAT(R0) ;ПРОВЕРЯЕМ НЕ МУЛЬТИПЛЕКСОР ЛИ ЭТО BNE MUX ;NE -> ДА, ПРИПЛЫЛИ. ;СЧАСТЬЕ ЕСТЬ И У НАС ОБЫЧНЫЙ DL11. В ПОЛЕ T.CSR БЛОКА УПРАВЛЕНИЯ ТЕРМИНАЛОМ ;(TCB) ХРАНИТСЯ АДРЕС CSR КЛАВИАТУРЫ. ADD #T.CSR,R0 ;ПОЛУЧАЕМ УКАЗАТЕЛЬ НА CSR MOV @R0,R5 ;СОХРАНЯЕМ ЕГО В R5 MOV #FAKE,@R0 ;ПОДСТАВЛЯЕМ ЛЕВЫЙ АДРЕС ВМЕСТО НЕГО ;И ПУСТЬ СИСТЕМА ПОДАВИТСЯ ;) BR 20$ ;ДАЛЬШЕ ОБЩИЙ КОД ;У НАС ОДНОТЕРМИНАЛЬНАЯ СИСТЕМА. ТУТ ВСЕ ПРОСТО: АДРЕС РЕГИСТРА КЛАВИАТУРЫ ;ХРАНИТСЯ ПО СМЕЩЕНИЮ $TTKS В RMON. 10$: MOV $TTKS(R0),R5 ;СОХРАНЯЕМ CSR В R5 ;СОБСТВЕННО ВСЕ. С ЭТОГО МЕСТА ИМЕЕМ ОБЩИЙ КОД, CSR В R5, ВСЕ ОБРАЩЕНИЯ ;К ТЕРМИНАЛУ ЧЕРЕЗ НЕГО И ДЕЛАЕМ. 20$: CLR @R5 ;ЗАПРЕЩАЕМ ПРЕРЫВАНИЯ ОТ КЛАВИАТУРЫ ... ;ПО ВЫХОДУ ИЗ ПРОГРАММЫ НЕ ЗЫБЫВАЕМ РАЗРЕШИТЬ ПРЕРЫВАНИ ОТ КЛАВИАТУРЫ ;И ВОССТАНОВИТЬ АДРЕС CSR ЕСЛИ СИСТЕМА МНОГОТЕРМИНАЛЬНАЯ. FAKE:: .BLKW 4 ;ФАЛЬШИВЫЙ НАБОР CSR ЧТОБ МОНИТОР ;ИМИ ПОДАВИЛСЯ
Можно было бы конечно разобрать случай использования напрямую регистров в TSX, но это отдельная тема и без особого смысла: в TSX любой функционал ради которого в RT-11 используют регистры можно включить и без этого, не говоря уже о последствиях прямого тыкания в железо в многопользовательской системе![]()
Последний раз редактировалось form; 23.11.2011 в 06:52.
PDP-11/83, Электроника МС0511 (УК-НЦ), DECserver 90M
Q-Bus: H9278-A, DLV11-J, DZQ11, DHV11, DELQA-M, LPV11, CQD-420/TM, DRV11
PMI: KDJ11-BF, MSV11-JE
VT220, CM7209
form, это как шпоргалка великая информация - но поворчи ещё пожалуйста:
1. Нужны ли такие ухищрения если мне просто в цикле надо постоянно клавиатуру
опрашивать ???
2. Как победить проскоки ? то есть у меня два цикла 1 ждет нажатия кнопки и когда
дожидается запускается второй из которого еxit так-же по нажатию, но exit срабатывает сразу ??? И это реальная проблема для меня ))) Я же игру собрался делать )))
1. Нужны если требуется гарантированная совместимость с любыми системами. Наиболее частая проблема которая встречается - многотерминальная система разрешает прерывания автоматом и половина ввода попадает в систему вместо программы, а также система генерит эхо для этого ввода. Получается каша.
2. Проскоков быть не должно если прерывания от клавиатуры запрещены. Если они разрешены, см проблему в п. 1
Как минимум нужно сделать CLR @#177560 - в однотерминальной системе этого достаточно.
Насчет выскакивания сразу: а ты собственно код клавиши нажатой извлекаешь из регистра данных?
---------- Post added at 23:12 ---------- Previous post was at 23:02 ----------
Вот для примера подпрограмма POLL которая либо возвращает код нажатой клавиши в R0 либо устанавливает бит C если ничего нажато не было
По метке 10$ о бите C не заботимся - он уже очищен командой TST выше.Код:POLL: TSTB @#177560 ;ЧТО-НИБУДЬ НАЖАТО? BMI 10$ ;MI -> ДА SEC ;УСТАНАВЛИВАЕМ ПРИЗНАК ОТСУТСТВИЯ НАЖАТИЯ RETURN ;ВОЗВРАТ 10$: MOVB @#177562,R0 ;ДА, ПОЛУЧАЕМ КОД RETURN ;ВОЗВРАТ
Последний раз редактировалось form; 22.11.2011 в 20:06.
PDP-11/83, Электроника МС0511 (УК-НЦ), DECserver 90M
Q-Bus: H9278-A, DLV11-J, DZQ11, DHV11, DELQA-M, LPV11, CQD-420/TM, DRV11
PMI: KDJ11-BF, MSV11-JE
VT220, CM7209
НУ дя ! И эта скотина второй цикл игнорирует и как-будто и небыло повторного
обнуления реагистра адреса !!!
да но у меня конкретная кнопка для выхода из 1 цикла и из 2 второго, допустим это "пробел" или "ентер"
я сравниваю 177562 с кодом нужной кнопки если это не ентер идут другие подпрограммы, а если "ентер"
выход и запуск цикла 2 который сразу кушает ентер из первого цикла и хлоп проскакивает, что за гадство такое?
ну вот смотри примерно такой тупой тупой листинг:
Код:... var inkey origin 177560B: integer; key origin 177562B: integer; ... repeat inkey:=0; ... case key of тра - та та та end; ... until key=13; дальше такая же примерно бодяга но условие until срабатывает сразу!!!
Последний раз редактировалось hobot; 22.11.2011 в 20:42.
Покажи пример.
Что такое обнуление регистра адреса?
---------- Post added at 23:19 ---------- Previous post was at 23:13 ----------
Кстати о совместимостях. Теоретически можно представить себе, что если прога сделана для УКНЦ, то уж там-то не на что натыкаться. Ан нет: и на УКНЦ можно поставить многотерминальную систему и успешно запользовать С2 как второй терминал![]()
PDP-11/83, Электроника МС0511 (УК-НЦ), DECserver 90M
Q-Bus: H9278-A, DLV11-J, DZQ11, DHV11, DELQA-M, LPV11, CQD-420/TM, DRV11
PMI: KDJ11-BF, MSV11-JE
VT220, CM7209
С любовью к вам, Yandex.Direct
Размещение рекламы на форуме способствует его дальнейшему развитию
Не вижу второго цикла.
"case key of" может вообще не работать - зависит от реализации компиляторы. Если он каждый из case'в проверяет напрямую из key, то первая же проверка разрешает нажатие следующей клавиши, которая может быть нажата до конца всех проверок.
вообще когда такие вещи делаются на языках высокого уровня нужно представлять себе во что это выльется после компиляции
кроме того у тебя вообще не видно опроса клавиатуры, зато прерывание в цикле запрещается постоянно
---------- Post added at 23:31 ---------- Previous post was at 23:25 ----------
Вот для понимания. Синтакс языка могу напутать - давно не паскалил, а дос запускать чтобы быстро в трубо-паскале проверить лень
хотя вобщем-то есть DEC паскаль, но думаю и так понятно что я имел в видуКод:inkey := 0; repeat while (inkey and 128) = 0 do; (* ждем нажатия *) ch := key; case ch of ...![]()
PDP-11/83, Электроника МС0511 (УК-НЦ), DECserver 90M
Q-Bus: H9278-A, DLV11-J, DZQ11, DHV11, DELQA-M, LPV11, CQD-420/TM, DRV11
PMI: KDJ11-BF, MSV11-JE
VT220, CM7209
не совсем понимаю почему такая конструкция ???
на УКНЦ паскаль отличается, досовский не так утроен
синтаксис всё фигня
на голом ассемблере я игру ваять буду лет 100, поэтому буду делать
на паскале с макро-вставками в ЭМУЛЯТОРЕ УКНЦ, то есть считай на УКНЦ !!! )))
а второй цикл такой-же как и первый
обнуляет регистр адреса
смотрим регистр данных
если ентер выходим - form я тебе клянусь он проскакивает !!!
Обнуление всего лишь запрещает прерывания. Все. В цикле это делать бесполезно. Далее у тебя в цикле тупо читается код нажатой клавиши, но при этом не проверяется нажали ее сейчас или это осталось на память с прошлого раза - еще когда ты набирал команду запуска программы.
Для того и конструкция - надо проверять 7 бит в 177560 и когда он установлен (клавиша нажата) - только тогда и читать ее.
PDP-11/83, Электроника МС0511 (УК-НЦ), DECserver 90M
Q-Bus: H9278-A, DLV11-J, DZQ11, DHV11, DELQA-M, LPV11, CQD-420/TM, DRV11
PMI: KDJ11-BF, MSV11-JE
VT220, CM7209
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)