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 - Анекдоты...


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

Похожие статьи:
Почта - пришло письмо от Алекса Ксора.
Путеводитель - подробное содержание номера.
c-jeff^gBg - она: Бабы и сценеры.
Программирование - процедура индикатора громкости музыки.
Обзор - обзор свежих релизов: Lord of Chaos, F-19 Stealth Fighter, Carrier Command, The Simpsons, Gauntlet 3, The Addams Family, Wild West Seymour, Sly Spy, Paris To Dakar, Duck Out, Johangir Khan World Championchip Squash, The Amazing Adventures of Robin Hood.

В этот день...   31 марта