приведет к тому, что текст из encrypt.txt будет выведен на экран, зашифрованный или расшифрованный ROT13, в зависимости от того, был ли он зашифрован до этого.
Рассмотрим все команды, которые может поддерживать символьное устройство, и буфера запросов, которые им передаются.
00h: инициализация (уже рассмотрена)
03h: IOCTL-чтенне (если установлен бит 14 атрибута)
+0Eh: 4 байта - адрес буфера
+12h:2 байта - на входе - запрашиваемое число байтов
на выходе - реально записанное в буфер число байтов
004h: чтение из устройства структура буфера для символьных устройств совпадает с 03h
05h: чтение без удаления символа из буфера
+ODh: на выходе - прочитанный символ, если символа нет - установить бит 9 слова состояния 06h: определить состояние бу4)ера чтения, если в буфере нет символов для чтения - установить бит 9 слова состояния
07h: сбросить буфер ввода
08h: запись в устройство
+OEh: 4 байта - адрес буфера
+12h: 2 байта - на входе - число байтов для записи
на выходе - число байтов, которые были записаны
09h: запись в устройство с проверкой аналогично 08h
0Ah: определить состояние буфера записи, если в устройство нельзя писать - установить бит 9 слова состояния
0Bh: сбросить буфер записи
0Ch: IOCTL-запись (если установлен бит 14 атрибута), аналогично 08h
0Dh: открыть устройство (если установлен бит 11 атрибута)
0Eh: закрыть устройство (если установлен бит 11 атрибута)
11h: вывод, пока не занято (если установлен бит 13 атрибута), аналогично 08h в отличие от функций записи здесь не считается ошибкой записать не вce байты
13h: обобщенный IOCTL (если установлен бит 6 атрибута)
+13h: 4 байта - адрес структуры данных IOCTL - соответствует структуре, передающейся в DS:DX для INT 21h, AX = 440Ch
19h: поддержка функций IOCTL (если установлены биты 6 и 7 атри-бута)
+0Dh: байт - категория устройства
+0Eh: байт - код подфункции
Если эта комбинация подфункции и категории устройства не поддерживается драйвером - надо вернуть ошибку ОЗП в слове состояния.
Создадим драйвер символьного устройства. Упрощая задачу, реализуем только функции чтения из устройства и будем возвращать соответствующие ошибки для других функций.
Блочные устройства
Блочными устройствами называются такие устройства, на которых DOS может организовать файловую систему. DOS не работает напрямую с дисками через BIOS, а только с драйверами блочных устройств, каждое из которых представляется системе как линейный массив секторов определенной длины (обычно 512 байт) с произвольным доступом (для BIOS, к примеру, диск - это четырехмерный массив секторов, дорожек, цилиндров и головок). Каждому загруженному устройству DOS присваивает один или несколько номеров логических дисков, которые соответствуют буквам, используемым для обращения к ним. Так, стандартный драйвер дисков получает буквыА, В, С и так далее, по числу видимых разделов на диске.
Рассмотрим атрибуты и команды, передающиеся блочным устройствам.
Атрибуты:
бит 15: 0 (признак блочного устройства)
бит 14: поддерживаются IOCTL-чтение и запись
бит 13: не требует копию первого сектора FAT, чтобы построить ВРВ
бит 12: сетевой диск
бит 11: поддерживает команды открыть/закрыть устройство и проверить, является ли устройство сменным
биты 10-8:000
бит 7: поддерживается проверка поддержки IOCTL
бит 6: поддерживается обобщенный IOCTL и команды установить и определить номер логического диска биты 5-2:0000
бит 1: поддерживаются 32-битные номера секторов бит 0: 0
Команды и структура переменной части буфера запроса для них (только то, что отличается от аналогичных структур для символьных устройств):
00h: инициализация
+0Dh: - байт количество устройств, которые поддерживает драйвер
+12h: 4 - байта дальний адрес массива ВРВ-структур (по одной для каждого устройства)
ВРВ - это 25-байтная структура (53 для FAT32), которая описывает блочное устройство. Ее можно найти по смещению 0Bh от начала нулевого сектора па любом диске:
+0: 2 байта - число байтов в секторе (обычно 512)
+2: байт - число секторов в кластере (DOS выделяет пространство па диске для файлов не секторами, а обычно более крупными единицами - кластерами. Даже самый маленький файл занимает один кластер)
+3: 2 байта - число секторов до начала FAT (обычно один - загрузочный)
+5: байт - число копий FAT (обычно 2) (FAT - это список кластеров, в которых расположен каждый файл. DOS делает вторую копию, чтобы можно было восстановить диск, если произошел сбой во время модификации FAT)
+6: 2 байта - максимальное число файлов в корневой директории +8- 2 байта - число секторов на устройстве (если их больше 65 536 - здесь записан 0)
+0Ah: байт - описатель носителя (0F8h - для жестких дисков, 0F0h - для дискет на 1,2 и 1,44 Мб, а также других устройств)
+0ВП:2 байта - число секторов в одной копии FAT (0, если больше 65 535)
+0Dh:2 байта - число секторов па дорожке (для доступа средствами BIOS)
+0Fh: 2 байта - число головок (для доступа средствами BIOS)
+11h: 4 байта - число скрытых секторов
+15h: 4 байта - 32-битное число секторов на диске
(следующие поля действительны только для дисков, использующих FAT32)
+16h: 4 байта - 32-битное число секторов в FAT
+1Dh:байт -флаги
бит 7: не обновлять резервные копии FAT
биты 3-0: номер активной FAT, если бит 7=1
+lFh: 2 байта - версия файловой системы (0000h для Windows 95 OSR2)
+21h: 4 байта - номер кластера корневой директории
+25h: 2 байта - номер сектора с информацией о файловой системе (0FFFFh, если он отсутствует)
+27h: 2 байта - номер сектора запасной копии загрузочного сектора (0FFFFh, если отсутствует)
+29h: 12 байт - зарезервировано
Для всех остальных команд в поле буфера запроса со смещением +1 размещается номер логического устройства из числа обслуживаемых драйвером, к которому относится команда:
01h: проверка носителя
+ODh: бант - на входе - описатель носителя
на выходе - 0FFh, если диск был сменен
0lh, если диск не был сменен
00h, если это нельзя определить
+OFh: 4 байта - адрес ASCIZ-строки с меткой диска (если установлен бит 11 в атрибуте)
02h: построить ВРВ
+0Dh: описатель носителя
+0Eh: 4 байта - на входе - дальний адрес копни первого сектора FAT на выходе - дальний адрес ВРВ
03h: IOCTL-чтение (если установлен бит 14 атрибута)
04h:чтение из устройства
+ODh: байт - описатель носителя
+12h: 2 байта - на входе - число секторов, которые надо прочитать
на выходе - число прочитанных секторов
+16h: 2 байта - первый сектор (если больше 65 535 - здесь 0FFFFh)
+18h: 4 байта - на выходе - адрес метки диска, если произошла
ошибка 0Fh
+lCh: 4 байта - первый сектор
08h: запись в устройство
структура буфера аналогична 04h с точностью до замены чтения на
запись
09h: запись в устройство с проверкой аналогично 08h
0Сh: IOCTL-запись (если установлен бит 14 атрибута)
0Dh: открыть устройство (если установлен бит 11 атрибута)
0Eh: закрыть устройство (если установлен бит 11 атрибута)
0Fh: проверка наличия сменного диска (если установлен бит 11
атрибута):
драйвер должен установить бит 9 слова состояния, если диск сменный,
и сбросить, если нет
13h: обобщенный IOCTL (если установлен бит 6 атрибута)