Пакет документации о рестартах iS-DOS 1969 г.

Рестарты - DOS.SYS (#10...#1F).


#10 (16) $g_cnfg

Этот рестарт выдает на выходе в HL' адрес вектора конфигурации ядра (см. ПРИЛОЖЕНИЕ 3) и системное блочное устройство S: в регистре A. Входные регистры не влияют. Флаг C на выходе роли не играет. Для примера рассмотрим перехват рестарта опроса клавиатуры, что может быть полезно, например, чтобы подвесить попискивание на клавиши.

LD C,$g_cnfg

RST 16

EXX

LD BC,8

ADD HL,BC                 ;адрес 0-го уровня DOS

LD E,(HL)

INC HL

LD D,(HL)

LD HL,14                     ;$key*2

ADD HL,DE                 ;KEY

LD (FN_A+1),HL

LD E,(HL)

INC HL

LD D,(HL)

LD (FN_RST+1),DE

PUTADR       LD DE,KEY

FN_A          LD HL,0

DI

LD (HL),E

INC HL

LD (HL),D

EI

RET

KEY

FN_RST CALL 0

Теперь при каждом вызове рестарта $key управление будет передаваться Вашей программе KEY, где Вы можете делать всё что угодно до и после обращения к драйверу. Если вздумаете оформить программу в виде резидента, а это самое разумное, не забудьте, что резидента могут сдвинуть, при этом надо заново положить новый адрес в таблицу рестартов DOS'а. Не забудьте также восстановить все как было при снятии резидента.

#11 (17) $g_key

Рестарт выдает в HL' адрес вектора символьного устройства ввода, а в A - канал текущего устройства ввода (обычно 8). Входные регистры не влияют. Флаг C на выходе роли не играет.

Пример: используем счетчик прерываний для получения псевдослучайного числа в интервале от 1 до 16:

LD C,$g_key

RST 16

EXX

LD BC,-20

ADD HL,BC

LD A,(HL)

AND #F

INC A

Счетчик уменьшается на 1 каждое прерывание. Вы можете использовать его для запуска некоей процедуры через определенное время. Для этого в счетчик положите интервал времени в 1/50 долях секунды, а со смещением -14 адрес процедуры. Через этот же вектор Вы можете получить доступ к цепочке процедур вызываемых по прерываниям. Цепочка устроена очень просто: перед каждой процедурой цепочки резервируются 2 пустых байта, являющихся признаком конца цепочки. При установке в цепочку следующего "звена" сюда кладется его адрес. Занимается этим рестарт $l_im2(#1E).

LD C,$g_key

RST 16

EXX

LD BC,-16

ADD HL,BC

LD E,(HL)

INC HL

LD D,(HL)

EX DE,HL           ;HL=адрес 1-го звена цепи

;достанем следующий адрес:

1$          DEC HL

LD D,(HL)

DEC HL

LD E,(HL)

;если 0, то это конец цепи:

LD A,D

OR E

RET Z

;иначе работаем с ним, к примеру печатаем этот адрес на экране, или проверяем, не лежит ли этот адрес

;в интересующем нас драйвере или уровне...

CALL IMTST             ;DE сохраняется

EX DE ,HL

JR 1$

#12 (18) $g_typ

Рестарт возвращает в HL' адрес символьного устройства вывода и номер текущего устройства в регистре A (от #10 до #17). Входные регистры не влияют. Флаг C на выходе не играет роли. Как пример: переключение на другой драйвер печати на экране, используемый в программе tv.com:

$swap    LD C,$g_typ

RST 16

;Сохраним номер текущего устройства:

LD (DEV0+1),A

;Следующее устройство:

NEXT       INC A

;должно быть в пределах от #08 до #0F:

CP #10

JR NZ,$+3

RRA ; A=8

DEV0       CP 0

RET Z                      ;Других устройств нет

LD B,A                      ;сохраним номер

;Достанем драйвер:

LD C,$g_drv

RST 16

LD A,B

JR C,NEXT              ;устройства видимо нет

;Проверим 13-й байт драйвера: у .typ=0, у .lpr=1

EXX

LD BC,13

ADD HL,BC

LD A,(HL)

EXX

OR A

LD A,B                         ;номер устройства

JR NZ,NEXT

;Всё OK. Можно переключаться:

LD C,$swtyp              ;#1B

RST 16

RET C

LD C,$g_typ

RST 16

EXX

LD A,(HL)

;A=4/6 - горизонтальный размер символа в точках

...

#13 (19) $g_blk

Рестарт возвращает в HL' адрес символьного устройства вывода и номер текущего устройства в регистре A (от 0 до 7). Входные регистры не влияют. Флаг C на выходе роли не играет. Что касается примера, смотрите отрывок из программы format.com приведенный при описании рестарта $clear(#01).

#14 (20) $g_drv

Этот рестарт по номеру устройства в регистре A ищет драйвер. Если всё OK, то на выходе флаг C сброшен, A=номер канала драйвера, HL'=адрес тела драйвера. Возможные ошибки:

124 - Ошибка в структуре области каналов

125 - нет канала

Устроен этот рестарт очень просто и в принципе делает вот что:

LD C,$stchn             ;найти канал номер A

RST 16

RET C

EXX

LD A,(HL)

;номер канала драйвера (см. ПРИЛОЖЕНИЕ 7)

EXX

RST 16                    ;канал драйвера

RET C

EXX

INC HL

INC HL

INC HL

INC HL

;адрес тела драйвера (см. ПРИЛОЖЕНИЕ 8)

LD E,(HL)

INC HL

LD D,(HL)

EX DE,HL                ;HL=адрес тела драйвера

Примеры применения самого рестарта $g_drv см. описания рестартов $g_typ(#12) и $clear(#01).

#16 (22) $stchn

Сей рестарт по номеру в регистре A ищет соответствующий канал. Если находит, то:

флаг C сброшен

A сохранится

HL'-адрес тела канала

BC'-длина канала

DE'-указатель за последний канал (он же $g_cnf+36).

Возможные ошибки те же, что и у рестарта $g_drv(#14). Пример из предыдущего рестарта также будет полезен. Еще пример - добывание канала пути альтернативной (или текущей) панели:

LD C,$gmpan

RST 16

EXX

DEC BC

LD A,(BC)              ;текущая панель 0/1

INC BC

OR A

JR NZ,$+3             ;Z для текущей

INC BC

LD A,(BC)

LD C,$stchn

RST 16

RET C

EXX

INC HL

INC HL

INC HL

LD A,(HL)            ;канал пути панели

EXX

RST 16

RET C

EXX

;HL указывает на путь альтернативной панели.


 

#17 (23) $dlchn

Этот рестарт находит канал по номеру в регистре A и удаляет его. Возможные ошибки см. $g_drv(#14). В жизни этот рестарт, как и создание канала применяется не часто. Любят этим заниматься программы set.com, exebat.com, print.com. Каналы необходимы при установке резидентов и тем более драйверов (ведь устройства суть каналы). Каналы удобны там, где надо передать не очень большой объём информации от одной программы другой (print) или сохранить кое-что для себя, а памяти для буферов нет (exebat). Для примера напишем программку, удаляющую все лишние каналы пользователя. Они могут оставаться в системе при аварийном завершении работы программ их создававших. Каналы пользователя имеют номера с #18 по #D7, из них первые 5 обычно заняты под системные надобности. Например:

#18 - путь левой панели

#19 - "тропа" поиска командников (path)

#1A - левая панель

#1B - путь правой панели

#1C - правая панель

Поэтому начнём с канала #1D:

LD BC,#1D00+$dlchn

1$          LD A,B

CP #D8

RET Z

RST 16

JR NC,2$

;Флаг C: ошибка

CP 125             ;нет канала

SCF

RET NZ

2$          INC B

JR 1$

#18 (24) $crchn

Этот рестарт создает канал. Номер канала задается на входе в регистре A. Размер канала в регистре DE. Возможные ошибки:

124 - ошибка в структуре области каналов

126 - канал с таким номером уже есть

127 - неверная длина канала (DE=0)

128 - нет места для канала

При нормальном завершении работы рестарта адрес канала выдается на выходе в HL'. Рестарт необходим для таких системных трюков, как создание устройств и установка драйверов и резидентов. Им пользуются программы set.com и dev.com, т.к. только этим рестартом можно создавать каналы с номерами от #00 до #17 и от #D8 до #FF. Для создания же каналов пользователя предназначен следующий рестарт:

#19 (25) $newch

Этот рестарт также как и предыдущий создает канал, но номер ему он дает сам, выбирая наименьший свободный в диапазоне от #18 до #D7. Длину канала, как и для $crchn подавайте в DE. Возможны те же ошибки, что и у предыдущего рестарта, за исключением, пожалуй, ошибки 126. Зато можно схлопотать ошибку: 129 - нет свободного номера, но для этого придется постараться. Если все OK, то флаг C сброшен, а в регистре A будет номер созданного канала. Регистр HL' как и в предыдущем случае укажет на адрес тела канала. Пример:

ORG 24000

LD DE,CHSIZ

LD C,$newch

RST 16

RET C

PUSH DE

EXX

POP BC

LD DE,CHBUF

EX DE,HL

LDIR

XOR A

LD A,#F8

RET

CHBUF     DEFM |Канал пользователя|

CHSIZ    EQU $-CHBUF

Следующие 3 рестарта переключают устройства всех трех исдосовских типов: символьного ввода и вывода и блочные. Номер входного устройства всем трём рестартам подается в регистре B, причем имеют значение лишь 3 младших разряда, т.к. все 3 рестарта смены устройств маскируют входной параметр. Возможны ошибки:

121 - нет устройства, т.е. нет канала с номером B.

122 - нет драйвера, обслуживающего данное устройство.

124 - Ошибка в структуре области каналов

#1A (26) $swkey

Переключение устройств символьного ввода (клавиатурных). В теперешнем исдосе не применяется. В старых версиях на драйвере ttyin.blk "висели" 2 устройства. Одно было для работы в редакторе, т.е. на него переключались рестарты $smbgt(#6E) и $edstr(#7F). Другим устройством пользовались все остальные, и работало оно обычно лишь в режиме маленьких латинских букв. Т.о. развязывались режимы работы в строковом редакторе и в оболочке и утилитах, пользовавшихся рестартом $key(#07) напрямую или через рестарт $menu(#91). Однако, в момент переключения устройств останавливались макросы. Развязку пришлось осуществить другим способом, а от 2 устройств отказаться. В принципе никто не мешает написать программу, переключающуюся на другой драйвер клавиатуры и работающий с ним или даже с двумя поочередно.

#1B (27) $swtyp

Переключение устройств вывода на экран или принтер. Используется программами tv.com, edit.com и некоторыми программами печатающими на принтере, например: PrintLux, Picasso. Вход и выход описаны выше. Пример см. к рестарту $g_typ(#12).

#1C (28) $swblk

Переключение блочных устройств. Интерфейс стандартный для всех трех $sw... рестартов, и добавить тут решительно нечего. Применяется программами: arzt+, abc, format, doctor, практически всеми копировщиками. См. пример к рестарту $read(#0D).

Перемещение информации о текущем состоянии при работе с драйверами и устройствами можно представить в виде следующей схемы:

set.com: драйвер -> устройство

$ldnew(#1D): устройство -> вектор драйвер -> вектор

sw...(#1A-#1C): вектор -> старое устройство новое устройство -> вектор

Итак, set.com, загрузив драйвер, создает устройства (т.е. каналы), и копирует в них 8 байт из драйверов со смещения 8. Рестарты смены устройств сохраняют эти же 8 байт системного вектора в канале отключаемого устройства и грузят на их место аналогичные 8 байт из подключаемого устройства.

#1D (29) $ldnew

Этот рестарт используется при подключении новых устройств. И используется он, похоже, только программой set.com. На входе ему подают номер устройства в регистре A и адрес системного вектора минус 9 в регистре HL. Каналы устройства и драйвера должны быть уже созданы и заполнены. Из канала устройства рестарт достает 8 байт данных (со смещением 2, см. ПРИЛОЖЕНИЕ 7, перед описанием $g_drv(#14)) и копирует их в вектор соответствующего устройства (ПРИЛОЖЕНИЯ 2,5,6, см. рестарты $g_***(#11…#13)). Со смещением 0 в канале устройства рестарт добывает номер канала драйвера, по нему находит заполненный канал, в котором со смещением 4 (см. ПРИЛОЖЕНИЕ 8, перед рестартом $g_drv(#14)) находится адрес драйвера. После чего три точки входа в драйвер (смещения 2,4,6) копируются в системный вектор в позиции -8,-5,-2 соответственно. Нечто подобное делается и при переключении на другое устройство рестартами $sw***(#1A…#1C). Вот что делает set.com после загрузки или удаления любого резидента или уровня:

LD C,$g_key

LD B,3

1$          PUSH BC

RST 16

EXX

LD BC,-9

ADD HL,BC

LD C,$ldnew

RST 16

POP BC

INC C

DJNZ 1$

RET

#1E (30) $l_im2

Рестарт работает с цепочкой функций, вызываемых по прерываниям от таймера. Как уже рассказывалось при описании работы рестарта $g_key(#11), в исдосе по прерываниям вызывается сперва драйвер клавиатуры, а затем программы пользователя, образующие цепь. Перед точкой входа в каждую программу цепи резервируется 2 байта, для ссылки на следующую программу цепи. 0 в этих байтах является признаком конца цепочки. Рестарту на вход подается адрес устанавливаемой/снимаемой процедуры в регистре HL. Регистр A сообщает рестарту, устанавливать (A<>0) или удалять из цепи данную процедуру. На время вызова рестарта обязательно запретите прерывания! Возможная ошибка только одна и проявляется она лишь при снятии фоновой задачи: 39 - нет такой фоновой задачи.

Начало цепочки фоновых задач можно достать из вектора рестарта $g_key(#11)(см. выше)

Пример:

ORG 24000

DEFS 4                   ;2 точки входа резидента

LD A,-1

LD HL,IM_2

LD C,$l_im2

RST 16

RET C

XOR A

LD A,#F8

RET

DEFW 0

IM_2       LD A,25

DEC A

JR NZ,$+4

LD A,25

LD (IM_2+1),A

RET NZ

1$          LD A,0

CPL

LD (1$+1),A

OUT (-2),A

RET

Отлинкуйте эту программку с ключом /res, загрузите полученный резидент, установив на него файловый курсор и нажав <Enter>. Вызовите резидентную задачу командой @имя. В принципе этот же пример можно отлинковать и запустить как com-файл, но после подобного примерчика рекомендуем перезагрузиться, т.к. удаление из цепочки здесь не предусмотрено, а set.com при снятии резидента сам отключит его от цепочки IM 2.

#1F (31) $erdrv

Этот рестарт создан исключительно для драйвера sys_driv.blk, который вызывает его в случае ошибки, а рестарт всего лишь печатает ваши любимые окна и ждёт ответа.

BREAK

Retry <R>

Abort <A>

 

Disk Error

Track 0

Sector 0

 

No Disk!

Retry <R>

Abort <A>

 

Retry Abort

Ignore?

 

Read Only!

Retry <R>

Abort <A>

Интерфейс следующий:

B=0: "Disk Error", D=трек, E=сектор

B=1: "Read Only"

B=2: "No Disk"

B=3: "Break"

На выходе в регистре A код нажатой клавиши в ВЕРХНЕМ регистре.

Хотя этот рестарт формально является рестартом нижнего уровня, в 0-ом уровне находится лишь маленькая процедурочка, опрашивающая 7-ой бит 1-го байта вектора блочных устройств ($g_blk(#13), см. выше) и, если бит сброшен, обращающейся по адресу ERDEV (вектор ядра системы, смещение +38, доступен через рестарт $g_cnf(#10), см. выше). Вы можете перехватить на себя данное обращение драйвера или запретить драйверу обращаться к этому рестарту, установив 7-ой бит 1-го байта вектора в 1. После этого по любой ошибке драйвера управление будет возвращаться сразу вашей программе с установленным флагом C и уже знакомыми кодами ошибок 6,7 и 20. Так поступают программы format, doctor и т.п. (см. пример к рестарту $clear(#01)).

Пример "тормозов" из новой версии драйвера ed128-b.blk:

TRANS

;1.8.96 BREAK:

LD C,$ktest         ;нажата клавиша ?

RST 16

JR Z,1$               ;если нет, то иди на 1$

LD C,$key           ;какая клавиша ?

RST 16

CP #16                ;<Cs/Space> ?

JR NZ,1$

PUSH BC

LD BC,#300+$erdrv

RST 16

POP BC

CP "A"                ;"A": "ABORT"

LD A,20              ;отваливаем с ошибкой 20

SCF

RET Z

1$          …




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



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

Похожие статьи:
Разыскиваются - игры.
Fiction - Двухламповый исполнитель желаний.
Пять ролей на выбор - психологический тест-сказка.
Adventures - поезка на велосипедах.
How it was in Leningrad - Year 1992-1993. Meeting Amiga

В этот день...   25 апреля