ZX Club #04
16 сентября 1997

Soft group - Перехват системных ошибок в Basic и TR-DOS при программировании на ассмблере (процедура).

<b>Soft group</b> - Перехват системных ошибок в 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 - Анекдоты...


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Программистам - ассемблер: Экскурс в анатомию ZX
Paradox 2000 - Битва титанов: Спор Колотова Сергея/Serzh Soft с Селиным Дмитрием/Phantom Lord и Виктором/M.O.T. о том как надо делать демки.
От авторов - О временном прекращении выхода газеты.

В этот день...   24 января