|
ZX Club
#04
16 сентября 1997 |
|
Soft group - Перехват системных ошибок в Basic и TR-DOS при программировании на ассмблере (процедура).

Программисты, которые пытаются писать
программы высокого качества для работы на
компьютерах, совместимых с ZX Spectrum,
сталкиваются с некоторыми проблемами мето-
дического и практического плана.
Одна из них, пожалуй, наиболее неп-
риятная, состоит в том, что при выполнении
любых операций чтения/записи диска система
TR-DOS может очистить экран и выдать сооб-
щение о том, что произошла дисковая ошибка
или что на дискете установлен маркер защи-
ты от записи. После этого она спрашивает,
нужно ли попытаться повторить операцию,
прервать её или проигнорировать. Для прог-
раммиста проблема в том, что появляется
необходимость восстанавливать экран после
обращения к DOS. Кроме того, система изме-
няет номер текущего потока. И вообще, про-
грамма, работающая, скажем, в оконном ин-
терфейсе, должна полностью обрабатывать
свои ошибки в рамках этого интерфейса.
Далее я покажу, как перехватить опи-
санную функцию TR-DOS лучшим, на мой
взгляд, методом. К сожалению, в данном
случае нельзя выделить некоторый охваты-
вающий все возможные ситуации алгоритм,
потому будет приведен конкретный пример,
взятый из оконного интерфейса прикладных
программ, разработанного автором. Но сна-
чала несколько слов о том, как TR-DOS об-
ращается к основному ПЗУ компьютера.
Как известно, теневое ПЗУ системы
TR-DOS подключается на место основного ПЗУ
компьютера при обращении процессора к оп-
ределенным адресам памяти с целью считыва-
ния кода операции. Одним из таких адресов
является адрес #3D13 - точка входа для ис-
полнения функций TR-DOS. При таком подклю-
чении устанавливается специальный триггер
в Beta Disk Interface, и дополнительное
ПЗУ остается подключенным до обращения
процессора за кодом операции вне этого
ПЗУ. Тогда триггер сбрасывается.
Если же TR-DOS зачем либо нужно обра-
титься к основному ПЗУ (например, для очи-
стки экрана, вывода символов и т. п.), то
она делает это следующим образом:
1) на стек кладется адрес возврата к те-
кущей части или модулю TR-DOS;
2) на стек кладется адрес требуемой под-
программы из основного ПЗУ;
3) выполняется переход по адресу 23746;
4) поскольку это адрес в области ОЗУ,
теневое ПЗУ отключается (триггер сбрасы-
вается аппаратно);
5) по этому адресу расположена инструк-
ция RET, поэтому со стека берется адрес
подпрограммы в основном ПЗУ и она запус-
кается;
6) инструкция RET в конце запущенной
подпрограммы вызовет переход назад, в те-
невое ПЗУ системы TR-DOS.
Предлагаемый пример показывает, как
можно обратиться к TR-DOS так, чтобы не
позволить ей очистить экран и выдать свое
сообшение в нижнем окне экрана. Вместо
этого сообшение TR-DOS выдается в окне
"Сообщение системы" применяемого оконного
интерфейса. В примере есть обращения к
неописанным здесь процедурам оконного ин-
терфейса. Проектируя свою подпрограмму
аналогичного назначения, Вы можете встави-
ть на место вызовов этих процедур свои
специфические вызовы с аналогичными фун-
кциями.
В данном случае вызов TR-DOS разделен
на 3 этапа:
1) подготовительные операции: установка
перехватчиков;
2) непосредственно вызов TR-DOS по адре-
су #3D13 (с возможной работой перехватчи-
ков);
3) завершающие операции: снятие перех-
ватчиков.
Программа записана в мнемонике ассем-
блера HiSoft GEN Assembler Version 4.1.
Итак, первый этап - установка перехватчи-
ков.
DOSPRE SUB A
LD (RSTFLG),A ;сообщение DOS ещё
;не выдавалось
LD HL,$$DOSW
LD (RSTPTR),HL ;указатель в текс-
;те окна - куда заносить символы
CALL CLKON ;показать курсор в
;форме песочных часов - "длительная опера-
;ция"
CALL IM1 ;перевести систему
;в режим прерываний 1
;далее следуют действия по установке пе-
;рехватчиков
DOSSWP LD HL,DOS_ST ;первая область
;для обмена
LD DE,23746 ;вторая область
LD BC,3 ;длина области
SWAP2 LD A,(DE) ;обмен содержимого
;областей памяти
LDI
DEC HL
LD (HL),A
INC HL
JP PE,SWAP2
;таким образом, команда RET по адресу
;23746 заменена на команду JP DOSEMT
LD HL,(23633) ;это системная пе-
;ременная CURCHL
LD C,(HL)
INC HL
LD B,(HL) ;это адрес обра-
;ботчика вывода текущего канала
LD DE,(DOS_CH) ;в DOS_CH адрес
;нашего обработчика
LD (DOS_CH),BC ;меняем их местами
LD (HL),D
DEC HL
LD (HL),E
;таким образом, процедура вывода текущего
;канала подменена на специальную. Установ-
;ка перехватчиков закончена.
RET
;непосредственно вызов DOS
;после однократного запуска DOSPRE, можно
;много раз запускать DOS; после всего нуж-
;но запустить DOSEND
DOS PUSH AF
LD (IY),-1 ;"не было ошибки"
SUB A ;начальное значе-
;ние кода возврата TR-DOS
LD (23823),A
LD (23824),A
POP AF
CALL #3D13 ;запуск TR-DOS
LD A,(23823) ;установка флага
;CY по коду возврата TR-DOS
AND A
RET Z ;если код = 0, то
;CY = 0
SCF
RET
;область временного хранения команды перехода
DOS_ST JP DOSEMT
;временное хранение регистров
DOS_HL DEFW 0
DOS_BC DEFW 0
;адрес процедуры вывода в канал
DOS_CH DEFW DOSRST
;перехватчик доступа к основному ПЗУ;
;если этот модуль запущен, значит, TR-DOS
;вызывает подпрограмму основного ПЗУ
DOSEMT LD (DOS_HL),HL ;сохраняем регист-
;ры
LD (DOS_BC),BC
POP BC ;это адрес в ос-
;новном ПЗУ
PUSH AF
AND A
LD HL,#D6B
SBC HL,BC ;адрес = #D6B ?
;(подпрограмма очистки экрана)
JR Z,DOSCLS ;если да, запуска-
;ем новый модуль очистки
AND A
LD HL,#1601 ;адрес = #1601 ?
;(подпрограмма установки текущего потока)
SBC HL,BC
JR Z,DOSIGN ;если да, игнори-
;руем вызов, поток не изменяется
;вызываемая подпрограмма не есть одна из
;перехватываемых, значит, иполняем ее
POP AF
PUSH BC ;возврашение адреса на
;место
LD HL,(DOS_HL) ;возвращение ре-
;гистров
LD BC,(DOS_BC)
RET ; исполнение заказанной
;подпрограммы основного ПЗУ
DOSIGN POP AF
RET
;ненулевое значение этого флага говорит о
;том, что окно сообщения TR-DOS уже откры-
;то
RSTFLG DEFB 0
;адрес помещения очередного символа в
;текст окна
RSTPTR DEFW $$DOSW
;подпрограмма очистки окна, заменяющая
;подпрограмму очистки экрана
DOSCLS POP AF ;конкретные дейст-
;вия непринципиальны
LD HL,$$DOSW
LD DE,$$DOSW+1
LD BC,5*21-1
LD (HL),255
LDIR
LD HL,$$DOSW
LD (RSTPTR),HL
LD A,(RSTFLG) ;если окно не от-
;крыто
AND A
LD A,28
CALL Z,OPEN ;то открыть его
LD A,-1
LD (RSTFLG),A ;изменить флаг
JP REDRAW ;перерисовать ок-
;но
;подпрограмма вывода символа в окно, заме-
;няющая собой вывод символа в область "K"
;экрана
DOSRST PUSH BC
PUSH DE
PUSH HL
LD HL,(RSTPTR)
LD (HL),A
INC HL
LD (RSTPTR),HL
CALL TEXTON ;обновить текст в
;окне
POP HL
POP DE
POP BC
RET
;завершающие операции после серии вызовов
;DOS
DOSEND LD (IY),-1 ;"ошибки не было"
CALL IM2 ;вернуть режим
;прерываний 2
CALL CLKOFF ;убрать курсор в
;форме песочных часов
CALL DOSSWP ;вернуть назад все
;вектора переходов и указатели
LD A,(RSTFLG) ;если окно сообще-
;ния TR-DOS открывалось
AND A
CALL NZ,CLOSE ;то закрыть его
RET
Таким образом, если TR-DOS захочет в
процессе работы выдать сообщение Disk
error или Read only, то она первым делом
попытается очистить экран. Эта попытка бу-
дет обнаружена в DOSEMT и вместо очистки
экрана будет выполнен вывод окна сообщения
TR-DOS и его очистка.
Далее, TR-DOS попытается открыть ка-
кой-либо поток, связанный с каналом "K"
для выдачи сообщения. Эта попытка также
будет перехвачена и проигнорирована.
После этого переходом по адресу #10
система будет печатать свое сообщение.
Казалось бы, можно в той же подпрограмме
DOSEMT "поймать" и эту ситуацию и не пере-
хватывать вывод в текущий канал. Как пока-
зали эксперименты, это срабатывает, но для
вывода чисел TR-DOS использует процедуру
OUT_NUM, которую приходится в таком случае
также перехватывать и эмулировать, что
неудобно и неэлегантно. Гораздо проще пе-
рехватить вывод в канал на уровне ракорда
канала, как и сделано в DOSSWP.
В результате сообщение TR-DOS появ-
ляется в красивом многоцветном окне посре-
ди экрана, а не внизу. Пользователь может
ответить на запрос точно так же, как всег-
да. Кроме того, экран не нарушается, что
очень удобно для программиста. По заверше-
нии последовательности вызовов TR-DOS окно
закрывается (в процедуре DOSEND).
Проконсультироваться у автора
Вы можете, написав по адресу:
257010 Украина, Черкассы-10, а/я 1529
Курицыну Б. А.
Другие статьи номера:
От редакции - О новых разделах в газете. |
От редакции - Новости от Юза Гаррисона. |
Soft group - Перехват системных ошибок в Basic и TR-DOS при программировании на ассмблере (процедура). |
Club IM2 - Работа с прерываниями 2-го рода. (поезд из LASER B.) |
Covox - Что из себя представляет COVOX (схема). |
Enjoy - Анекдоты... |
Похожие статьи:
В этот день... 19 ноября