Разработка и исследование драйвера консоли

Понятие и назначение драйверов, схема взаимодействия прикладной программы и устройства. Разработка драйвера консоли и назначения компонентов, создание программы отладки драйвера и исследования его работы выполнении функций ввода-вывода в открытом режиме.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 20.11.2010
Размер файла 1,8 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

119

1. НАЗНАЧЕНИЕ ДРАЙВЕРОВ И ПОРЯДОК РАБОТЫ С ДРАЙВЕРАМИ В MS-DOS

Обычно в состав компьютера входят клавиатура, экран, принтер, диски и другие устройства. Представьте, сколько времени необходимо, чтобы написать программу непосредственного ввода и вывода одной строки. А если для 10 разнообразных принтеров или дисковых контролеров?

Некоторые задачи решаются благодаря BIOS, но лишь со стандартными устройствами. Например, распечатать текст на так называемом Windows-принтере в DOS невозможно. Но эта проблема решается достаточно просто. Соединительным звеном между программой и принтером является драйвер.

Работа со всеми устройствами в компьютере идет через драйверы. Такая структура DOS позволяет расширить стандартные функции и организовать обмен информацией практически с любым цифровым устройством.

Устройства разделяются на 2 группы: символьные и блочные.

Символьные передают по одному символу, например клавиатура модем и другие.

Блочные устройства передают данные блоками по несколько байт, например 512 или 1024 байт. Это диски, дисководы. Разделение на такие группы дает большие преимущества, потому что операционная система работает с устройством, несмотря на его аппаратные особенности.

Обмен между драйверами и операционной системой происходит с помощью запросов. Запрос содержит всю необходимую информацию для работы устройства: какую команду нужно выполнить, в каком виде вернуть данные и т.д. Также запрос является унифицированной структурой, что очень упрощает работу прикладных программ с устройством.

Ниже на Рис. 1.1 приведена схема взаимодействия прикладной программы и устройства. Непосредственное управление устройством из программы целесообразно применить для организации обмена информацией с нестандартным устройством. Работа через BIOS менее сложная задача, но использование этого метода ограничивает возможности программы, так как можно реализовать обмен информацией лишь со стандартными устройствами. Наиболее распространенный способ работы с устройствами, причем не только в MS-DOS, - работа через драйверы. Все языки высокого уровня для ввода-вывода используют функции int21h или функции драйвера.

Для сохранения адреса запроса во внутренних переменных драйверу или организация очереди запросов обслуживания вызывается процедура стратегии. Дальше управление передается процедуре прерывания, которая анализирует поля запроса и выполняет необходимые действия.

Рис. 1.1 Схема взаимодействия программы и устройства

2. РАЗРАБОТКА СИМВОЛЬНОГО ДРАЙВЕРА КОНСОЛИ

Структура драйвера консоли и назначения компонентов

Драйвер - это программа, структура которой отличается от com- и exe-программ. Драйвер должен начинаться с так называемого заголовка драйвера, который содержит разнообразную служебную информацию, далее идет блок описания данных, блок процедур Стратегии и Прерывания. Структура драйвера приведена на Рис.2.1. Структура заголовка драйвера приведена в Табл.2.1.

Табл. 2.1 Структура заголовка драйвера

Смещение, байт

Размер, байт

Имя поля

Описание

0

4

next

Указатель на заголовок следующего драйвера. Если смещение адреса следующего драйвера равняется FFFFh, это последний драйвер в цепочке

4

2

attrib

Атрибуты драйвера

6

2

strateg

Смещение программы стратегии драйвера

8

2

interrupt

Смещение программы обработки прерывания для драйвера

10

8

dev_name

Имя устройства для символьных или количество устройств, которые обслуживаются, для блочных устройств

Все драйверы связаны в цепочку. Поле next заголовка драйвера указывает на следующий драйвер (на его заголовок). Это поле имеет формат дальнего указателя и состоит из адреса сегмента и смещения. Признаком того, что данный драйвер является последним в цепочке, служит значение 0FFFFh в компоненте смещения поля next. При загрузке драйверов в память операционная система изменит содержимое поля next в заголовках драйверов для того, чтобы это поле указывало на заголовок следующего драйвера в цепочке.

Рис. 2.1 Структура драйвера

Поле attrib - это поле описывает устройство, которое обслуживает драйвер. Каждый бит слова характеризует ту или иную особенность устройства. Его структуру мы рассмотрим ниже.

Поле strateg и interrupt - это смещение процедуры стратегии драйвера и смещение процедуры обработки прерывания. Для обращения к драйверу MS-DOS формирует в своей области данных запрос, который состоит из заголовка стандартного формата и дополнительной структуры данных (переменной части запроса), длина и формат которой зависят от типа запроса. Дальше MS-DOS считывает из заголовка драйвера смещения процедуры стратегии и передает ей управление, записав в регистры ES:BX адрес заголовка запроса.

Процедура стратегии запоминает этот адрес во внутренних переменных драйвера для последующего использования

Процедура обработки прерывания считывает адрес заголовка запроса и выполняет функцию, номер которой записан в заголовке запроса. Результаты выполнения функции программа прерывания записывает в специально отведенные поля заголовка запроса, после чего процедура прерывания передает управление MS-DOS. Формат заголовка запроса приведен в Табл.2.2. Каждой команде драйвера соответствует своя структура запроса, заголовок запросов для всех команд общий. Структура запроса команды инициализации приведена в Табл.2.3, Неразрушающий ввод - Табл. 2.4 ,ввода - Табл. 2.5, структура запроса очистки ввода состоит только из заголовка запроса.

dev_name - поле для символьных устройств, в котором должно располагаться имя устройства, выровненное по левому краю. Это имя будет использоваться для обращения к драйверу.

На размер драйвера налагается такое же ограничение, как и на размер com-программ - 64 Кбайт, то есть один сегмент.

Табл. 2.2 Формат заголовка запроса

Смещение, байт

Размер, байт

Имя поля

Описание

0

1

Size

Общий размер блока запроса в байтах (длина заголовка запроса плюс длина переменной части запроса)

1

1

Unit

Номер устройства. Используется для блочных устройств; указывает, с каким именно устройством будет работает операционная система

2

1

Cmd

Код команды, которую требуется выполнить. Может иметь значение от 00h до 18h

3

2

status

Слово состояния устройства. Заполняется драйвером перед возвращением управления операционной системе

5

8

reserved

Зарезервировано

Табл. 2.3 Структура запроса команды Инициализации

Смещение, байт

Размер, байт

Имя поля

Описание

0

13

header

Заголовок запроса

13

1

n_units

Количество устройств, обслуживаемых драйвером. Это поле заполняется только блочным драйвером. Для символьного драйвера в это поле нужно записать значение 0

14

4

end_addr

Дальний адрес нижней границы резидентной части кода драйвера. В это поле драйвер записывает адрес байта памяти, следующего за областью драйвера, которая должна стать резидентной

18

4

parm

Дальний адрес строки параметров инициализации драйвера из файла config.sys . Эта строка содержит все, что находится в строке файла после команды 'DEVICE='. Она заканчивается символами перевода строки и возврата каретки 0Ah, 0Dh. При возврате драйвер блочного устройства должен записать в поле parm адрес массива указателей на блоки параметров BIOS (BPB ), по одному указателю на каждое устройство, обслуживаемое драйвером

22

1

drive

Номер устройства. В это поле при загрузке драйвера операционная система заносит номер, назначенный устройству, обслуживаемому драйвером. Например, для устройства А: это 0, для B: - 1 и т. д.

23

1

msg_flag

1 - отображение сообщения об ошибке, если в поле status заголовка запроса установлены соответствующие биты;0 - сообщение об ошибке не отображается

Табл. 2.4 Структура запроса команды Ввод

Смещение, байт

Размер, байт

Имя поля

Описание

0

13

header

Заголовок запроса

13

1

media

В этом поле драйверу передается байт-описатель среды носителя данных

14

4

buf_adr

Адрес буфера для передачи данных

18

2

count

Количество передаваемых байтов для символьных устройств или секторов для блочных устройств

20

2

sector

Номер начального логического сектора, если драйвер использует 16-битовую адресацию секторов, или 0FFFFh для 32-битовой адресации. Это поле не используется символьными драйверами

22

4

vol_id

Указатель на метку тома в формате ASCIIZ . Возвращается блочным драйвером, если он возвращает код ошибки 15 (неправильная смена диска). Это поле должно содержать ссылку на метку требуемого диска

26

4

sect32

Номер начального сектора, если содержимое поля sector равно 0FFFFh. Первым идет старшее слово номера сектора. Если обнаружена ошибка с кодом 15, в это поле записывается указатель на метку тома

Табл. 2.5 Структура команды неразрушающий ввод

Смещение, байт

Размер, байт

Имя поля

Описание

0

13

header

Заголовок запроса

13

1

byte

В это поле драйвер записывает извлеченный из буфера байт, который будет считан следующей командой ввода

Формирование слова атрибута драйвера

Рассмотрим слово атрибута драйвера. Назначение битов слова атрибута драйвера приведено в Табл. 2.6.

0-й и 1-й бит слова атрибута - по этому битам MS-DOS определяет драйвер консоли, который будет использоваться в системе для вывода и ввода. Биты необходимы для того, чтобы MS-DOS сформировала внутренние переменные согласно с текущим драйвером консоли, например, адрес драйвера в Списке Списков, таблица SFT и другие.

15-й бит слова атрибута - этот бит обозначает тип устройства: блочное или символьное. Консоль является символьным устройством, поэтому необходимо взводить этот бит. Назначение других битов понято из Табл.2.6.

Табл.2.6 Назначение битов слова атрибута драйвера

Бит

Назначение

0

1 - драйвер обслуживает стандартное устройство ввода; 0 - этот драйвер не обслуживает стандартное устройство ввода

1

1 - драйвер обслуживает стандартное устройство вывода; 0 - драйвер не обслуживает стандартное устройство вывода

2

1 - драйвер стандартного устройства NUL; 0 - драйвер не обслуживает устройство NUL

3

1 - драйвер обслуживает часы

4

Для работы с устройством можно использовать средство быстрого символьного вывода - прерывание INT 29h. Это прерывание предназначено для быстрого вывода символа на консоль, код символа необходимо записать в регистр AL

5

Зарезервировано, бит должен быть равен 0

6

1 - разрешено использование драйвером функций IOCTL ; 0 - функции IOCTL не поддерживаются

7

1 - устройство может принимать запросы IOCTL (интерфейс IOCTL будет описан позже)

8-10

Эти биты зарезервированы и должны быть равны 0

11

1 - поддерживаются функции открытия/закрытия устройства (OPEN/CLOSE); 0 - функции OPEN/CLOSE для символьных устройств не поддерживаются

12

Зарезервировано, бит должен быть равен 0

13

1 - для символьных устройств поддерживается функция вывода до получения состояния занятости устройства; 0 - функция вывода до состояния занятости не поддерживается

14

1 - поддерживаются функции чтения и записи через интерфейс IOCTL 0 - функции чтения/записи через интерфейс IOCTL не поддерживаются

15

1 - символьное устройство; 0 - блочное устройство

Для правильной работы консольного драйвера поле attrib должно иметь значение 1000 0000 0000 0011b или 8003h.

Разработка схемы алгоритма драйвера

Структура драйвера приведена на Рис.2.2.

Рис. 2.2 Структура драйвера

Процедура СТРАТЕГИЯ является очень простой, ее работа описана ранее.

Блок-схема алгоритма процедуры Стратегия изображена на Рис.2.3

Рис. 2.3 Блок-схема алгоритма процедуры Стратегия

На Рис. 2.4. приведена блок-схема алгоритма процедуры прерывания. Ее алгоритм практически не отличается от аналогичных процедур других символьных устройств за исключением реализации команд драйвера.

Рис. 2.4 Блок-схема алгоритма процедуры прерывания

На Рис.2.5. приведен алгоритм команды INIT. Данная процедура выводит сообщение на экран и в случае необходимости инициализирует данные драйвера, а так же возвращает в соответствующих полях запроса адрес конца драйвера.

Рис. 2.5 . Алгоритм команды INIT

В процедуре INPUT есть переменная sav, в которой хранится считанный скан-код расширенной клавиши, и при следующем чтении возвращается содержание sav, то есть обращения к функциям BIOS не происходит. Блок-схема алгоритма команды INPUT приведена на Рис.2.6.

Рис. 2.6 Блок-схема алгоритма команды INPUT

Очистка буфера клавиатуры нужна для того, чтобы предотвратить считывание ранее введенных клавиш. Используется функция BIOS 01h int 16h для проверки статуса буферу клавиатуры, если буфер не пустой то считывается символ. Это происходит в цикле.

Блок-схема алгоритма команды INPUT_FLUSH изображена на Рис.2.7.

Рис.2.7 Блок-схема алгоритма команды INPUT_FLUSH

3. РАЗРАБОТКА ПРОГРАММЫ ОТЛАДКИ ДРАЙВЕРА (TEST1)

Структура программы и назначения компонентов

Программа отладки драйвера состоит из двух модулей.

Модуль test1.pas является главным модулем. В нем реализованы диалог с пользователем, формирование запроса драйвера, а также процедуры тестирования процедур Стратегия и Прерывание и команд INIT, INPUT и INPUT_FLUSH.

Вторым модулем является сам драйвер, который принимает адрес заголовка запроса от первого модуля и обслуживает этот запрос.

Таким образом, эта программа дает возможность отладки драйвера без его загрузки в систему, что уменьшает трудоемкость и общую сложность тестирования и отладки драйвера.

Разработка схемы алгоритма программы

На Рис. 3.1 изображен алгоритм тестовой программы №1.

Рис. 3.1 Схема алгоритма тестовой программы №1

На Рис. 3.2 изображен общий алгоритм тестовых процедур.

Алгоритмы процедур testinit, testread и testflush мало чем отличаются друг от друга. Но в процедуре testflush выводится буфер клавиатуры до вызова драйвера и после вызова.

Рис. 3.2 Общий алгоритм тестовых процедур

Анализ результатов отладки драйвера

Так как обмен программы и драйвера проходит через запросы, то достаточно проконтролировать поля запроса до и после обращения к драйверу.

Процедура отладки команды INIT. Как видим на Рис. 3.3 команда INIT вывела строку о своей инициализации, причем драйвер вернул конец драйвера в запросе. Мусор в счетчиках появляется вследствие слияния сегментов кода объектного файла драйвера и тестирующей программы.

Процедура отладки команды INPUT. На Рис. 3.4 Было введена 5 символов, команда взвела флаг СДЕЛАНО в слове статуса (0-й бит).

Рис. 3.3Отладка команды INIT

Рис. 3.4 Отладка команды INPUT

Процедура отладки команды FLUSH_INPUT. Как видно на Рис. 3.5 процедура выводит буфер клавиатуры и позволяет ввести пользователю символы, далее буфер клавиатуры выводится перед вызовом команды драйвера и после вызова для отображения правильности работы команды.

Рис. 3.5 Отладка команды FLUSH_INPUT

4. РАЗРАБОТКА ПРОГРАММЫ ИССЛЕДОВАНИЯ РАБОТЫ УСТАНОВЛЕННОГО ДРАЙВЕРА КОНСОЛИ (TEST2)

Назначение программы

Программа исследования работы установленного драйвера консоли предназначена для проверки и исследования связей DOS через установленный драйвер с BIOS. Эта программа с помощью функций DOS 06h int 21h, 3fh int 21h и 0сh int 21h, проверяет работу команд INPUT и INPUT_FLUSH драйвера, исследуются различия между ASCII и Бинарным режимами работы драйвера, а также работа в режиме закрытого/открытого драйвера.

Разработка схемы алгоритма программы

Схема алгоритма программы приведена на Рис. 4.1.

Рис. 4.1Схема алгоритма Test 2

Анализ результатов исследования работы драйвера консоли при выполнении функций ввода-вывода int 21h в режиме открытого драйвера

Драйвер считается открытым, когда стандартные файлы ввода-вывода открыты (0-й и 1-й дескрипторы).

Протестируем функции в ASCII режиме драйвера.

Тестирование функции 06h. Как известно функция DOS 06h int21h - функция консольного посимвольного ввода-вывода. Ввод осуществляется без эха на экране и без ожидания, управляющим символом является FFh, который переводит функцию в режим ввода. При отсутствии символа в буфере клавиатуры взводится процессорный флаг CF.

Сначала считывается 5 символов из буфера клавиатуры, затем эти символы выводятся на экран этой же функцией. Так как функция без ожидания, то непосредственно перед вызовом 06h пользователю предоставляется возможность заполнить буфер клавиатуры. Выход из этого режима осуществляется по нажатию клавиши Left Shift. Так же на экран выводится буфер клавиатуры, выход из этого режима также реализован по нажатию клавиши Left Shift,так как использование функций BIOS изменяет содержимое буфера клавиатуры. При тестировании функции в режиме открытого драйвера функция работает без каких-либо особенностей. На Рис. 4.2 изображен экран непосредственно перед вызовом функции 06h.

Рис. 4.2 Экран до вызова функции 06h int 21h

На Рис. 4.3 изображен экран после вызова функции 06h, справа счетчик ввода изменился на 5 (5 вызовов 06h).

Рис. 4.3 Экран после вызова функции 06h

Тестирование функции 0сh int 21h. Функция 0сh - очистка ввода (буфера клавиатуры) с последующим вызовом функции, номер которой загружен в al. Функция очищает буфер клавиатуры, что предотвращает считывание ранее введенных символов. Фактически функция вызывает команду драйвера Очистка Ввода. В процедуре тестирования функция 0сh после очистки вызывает 01h, что демонстрирует работу очистки ввода. Тестовая процедура дает возможность пользователю заполнить буфер клавиатуры и при нажатии клавиши Left Shift продолжает работу. На Рис. 4.44.4 можно увидеть, что драйвер клавиатуры заполнен некоторыми символами.

Рис. 4.4 Экран до вызова функции 0ch

На Рис. 4.5 видно, что функция 0сh вызвала команду драйвера Очистка Ввода. Далее управление передалось функции 01h, которая считала символ “w”.

Рис. 4.5 Экран после вызова функции 0ch

Тестирование функции 3fh. Функция 3fh предназначена для чтения блока байт из файла с использованием описателей файлов (так называемый handle-ориентированный ввод). Также с помощью этой функции можно осуществить ввод c консоли. Для этого используются стандартные описатели консоли (0-й - клавиатура , 1-й - экран). В регистре cx - количество байт для чтения. Процедура тестирования вызывает функцию 3fh для чтения 5 байт. Но фактически при работе этой функции можно ввести до 127 символов, которые помещаются в Системный буфер, а из системного буфера переписываются в пользовательский 5 байт. Чтение осуществляется до нажатия клавиши Enter. При последующих обращениях в пользовательский буфер будут записываться данные из системного буфера до тех пор, пока он не окажется пустой.

Опишем механизм работы Системного буфера. Системный буфер - буфер в сегменте данных DOS, который функция 3fh при работе с консолью использует как промежуточный. Для доступа к системному буферу используется функция DOS 52h. Функция MS-DOS с номером 52h (прерывание int 21h) является недокументированной функцией, которая возвращает указатель на список внутренних переменных MS-DOS Список Списков(List of Lists). Указатель возвращается в паре ES:BX, где ES - сегмент данных DOS. Как раз перед этим списком в слове ES:[BX-4], находится смещение системного буфера относительно сегмента данных MS-DOS (далее поле смещение системного буфера). Предположим, изначально буфер пуст. При чтении из стандартного файла ввода функцией # 3fh int 21h DOS проверяет значение смещения системного буфера, если он равен 0, то в буфер заносятся данные, введенные с клавиатуры. При этом поле смещение системного буфера указывает на символ, который будет считан при следующем обращении к буферу. При считывании символа с кодом 0Dh DOS автоматически дописывает в буфер символ с кодом 0Ah. При следующем обращении считывается символ с кодом 0Ah, далее DOS обнуляет поле смещения системного буфера, тем самым указывает на то, что буфер пуст. Фактически с момента считывания из буфера символа 0Dh DOS считает, что достигла конца буфера и дальнейшие операции с буфером (запись символа 0Ah и обнуление смещения буфера) являются подготовительными к приему новых данных. В функции 3fh это реализовано для полной эмуляции чтения из файла.

Вывод результатов ввода реализован через внутреннюю процедуру вывода строк.

На Рис. 4.6 функция 3fh ожидает ввода символов с клавиатуры.

Рис. 4.6 Ожидание ввода при выполнении функции 3fh

На Рис. 4.7 видно, что функция считывает символы до нажатия клавиши Enter, при этом в пользовательский буфер попали только первые 5 байт.

Рис. 4.7 Экран после вызова функции 3fh

Протестируем функции в бинарном режиме. Функции 06h и 0ch работают также как и ASCII режиме, исключение составляет функция 3fh. В бинарном режиме 3fh за одно обращение к драйверу считывает все затребованное количество байт без эха на экран. На Рис. 4.8 и Рис. 4.9 видно, что 3fh обращается к драйверу 1 раз, так как счетчики команд в замещающем драйвере выводятся после выполнения команды. Так же необходимо отметить то, что в бинарном режиме функция 3fh работает как при чтении из обычного дискового файла, т.е. работа ведется не через системный буфер, а напрямую; функция не реагирует на нажатие клавиши Enter.

Рис. 4.8 Вызов функции 3fh в бинарном режиме

Рис. 4.9 Экран после вызова функции 3fh в бинарном режиме

Анализ результатов исследования работы драйвера консоли при выполнении функций ввода-вывода int 21h в режиме закрытого драйвера

Особый интерес вызывает возможность закрытия и открытия драйвера.

Для исследования этого режима в тестовой программе №2 предусмотрены режимы “Закрыть драйвер на ввод”, “Закрыть драйвер на вывод”, ”Открыть драйвер”. Рассмотрим все эти режимы по порядку на примерах функций DOS.

Режим закрытия драйвера на вывод. В этом режиме вызывается функция 3Eh int 21h - закрытие файла, в качестве дескриптора файла используем описатели стандартного вывода (1-й описатель).

Исследование функции 0сh в режиме драйвера закрытого на вывод и на ввод не имеет смысла, так как данная функция ничего не выводит и не вводит.

Исследуем функцию 06h в режиме драйвера закрытого на вывод. Как видим на Рис. 4.10 буфер клавиатуры не пустой. На Рис. 4.11 видно, что функция 06h считала символы, но не вывела их на экран, следовательно, закрытие вывода для функции 06h работает. Более детально работу функции 06h мы рассмотрим в п.4.5.

Рис. 4.10 Буфер клавиатуры до вызова 06h

Рис. 4.11 Экран после вызова функции 06h в режиме закрытого драйвера

Исследуем функцию 3fh. На Рис. 4.12 изображен рабочий экран при выполнении функции 3fh. Как видим, закрытие драйвера на вывод для нее не работает, значит у 06h и у 3fh разные методы вывода на экран (далее рассмотрим этот вопрос более подробно).

Рис. 4.12 Экран при выполнении функции 3fh при закрытии на вывод

Теперь рассмотрим режим закрытия драйвера на ввод на примере функций 06h и 3fh. На Рис. 4.13 видно, что к драйверу не было обращений, значит, функция 3fh реагирует на закрытие дескриптора файла стандартного ввода.

Рис. 4.13 Работа функции 3fh в режиме драйвера закрытого на ввод

Функция 06h в режиме драйвера закрытого на ввод также теряет работоспособность, что видно на Рис. 4.14. Вместо введенного символа возвращается символ с кодом 06h, а также из буфера клавиатуры не считался ни один символ.

Рис. 4.14 Результаты работы функции 06h в режиме драйвера закрытого на ввод

Механизм взаимодействия MS-DOS и драйвера

Чтобы более четко представлять механизм работы DOS с консолью необходимо рассмотреть, как DOS взаимодействует с драйвером.

В операционной системе MS-DOS все драйверы скреплены в цепочку, каждый драйвер указывает на следующий. Чтобы получить адрес первого драйвера используется функция DOS 52h int 21h, она возвращает адрес Списка Списков - структуру внутренних переменных DOS. Эта структура описана в Списке Списков по смещению +12 находится указатель на консольный драйвер. Так же по смещению +4 находится указатель на таблицу файлов MS-DOS (System File Table, SFT). Именно эта таблица представляет наибольший интерес. Введение в DOS handle-ориентированной работы с файлами позволило значительно упростить написание программ, в том числе и работу со стандартными устройствами, такими как клавиатура, экран, экран ошибок, принтер. С точки зрения MS-DOS все вышеперечисленные устройства мало чем отличаются от обычных файлов, одни открыты только для чтения, другие только для записи и т.д. В таблице SFT хранится информация обо всех открытых файлах в системе. Структура таблицы SFT приведена в Табл.4.2.

Табл. 4.1 Структура Списка списков

Смещение, байт

Размер, байт

Имя поля

Описание

-2

2

mcb_seg

Сегмент первого блока памяти MCB

0

4

dev_cb

Указатель на первый блок управления устройствами MS-DOS (MS-DOS Device Control Block)

4

4

file_tab

Указатель на таблицу файлов MS-DOS

8

4

clock_dr

Указатель на драйвер CLOCK$ , установленный в файле config.sys или резидентный

12

4

con_dr

Указатель на драйвер CON , установленный в файле config.sys или резидентный

16

2

max_btbl

Максимальный размер блока (в байтах) для устройства, выполняющего передачу данных отдельными блоками

18

4

disk_buf

Указатель на структуру, описывающую дисковые буферы

22

4

drv_info

Указатель на массив информации об устройствах

26

4

fcb_tabl

Указатель на таблицу FCB

30

2

fcb_size

Размер таблицы FCB

32

1

num_bdev

Число устройств, выполняющих передачу данных отдельными блоками

33

1

lastdriv

Значение LASTDRIVE в файле config.sys (по умолчанию равно 5)

34

?

null_dr

Начало драйвера NUL. Этот драйвер всегда первый в списке драйверов MS-DOS

Табл. 4.2 Структура SFT

Смещение, байт

Размер, байт

Имя поля

Описание поля

0

4

next

Указатель на следующую таблицу файлов SFT

4

2

file_count

Количество файлов, описанных в этой таблице с помощью блоков DFCB

Таблица SFT состоит из DFCB блоков. Каждый такой блок описывает один файл. Структура DFCB блока приведена в Табл. 4.3. В DFCB блоке файла консоли записан адрес драйвера консоли. Изменяя этот адрес можно передавать управление другим драйверам консоли. На Рис. 4.14 приведен пример DFCB блока файла консоли.

Рис. 4.14 Пример DFCB блока файла консоли

Для исследования работы DOS с драйвером в тестовую программу №2 включен режим переключения драйвера. Этот режим разбит на подрежимы:

- удаление заменяющего драйвера из цепочки

- удаление заменяющего драйвера из цепочки и изменение адреса драйвера в Списке Списков

- удаление заменяющего драйвера из цепочки и изменение адреса драйвера в таблице SFT.

Табл. 4.3 Структура DFCB

Смещение, байт

Размер, байт

Имя поля

Описание

0

2

handl_num

Количество идентификаторов, связанных с данным файлом

2

1

access_mode

Режим доступа к файлу, заданный при открытии файла

3

2

reserv1

Зарезервировано

5

2

Dev_info

Информация IOCTL , полученная для устройства, на котором расположен этот файл

7

4

driver

Указатель на драйвер, обслуживающий устройство, содержащее файл

11

2

first_clu

Номер первого кластера, распределенного файла

13

2

time

Время последнего изменения файла в упакованном формате

15

2

date

Дата последнего изменения файла в упакованном формате

17

4

fl_size

Размер файла в байтах

21

4

offset

Текущее смещение внутри файла в байтах

25

2

reserv2

Зарезервировано

27

2

reserv7

Зарезервировано

29

3

Reserv3

Зарезервировано

32

1

reserv4

Зарезервировано

33

11

filename

Имя файла в формате FCB

44

2

reserv5

Зарезервировано

46

2

ownr_psp

Адрес блока PSP программы, открывшей файл

48

2

Reserv6

Зарезервировано

50

2

last_clu

Номер только что прочитанного кластера

52

4

reserv8

Зарезервировано

Исследуем, каким образом обеспечена работа функций 06h, 0сh, 3fh.

При удалении драйвера из цепочки работоспособность функций не нарушилась, следовательно, DOS не использует метод поиска драйвера консоли в цепочке. На следующем шаге изменим адрес драйвера в Списке Списков.

Как мы видим на Рис. 4.15 изменений в работе функции 06h нет (вывод по-прежнему ведется через заменяющий драйвер), значит, эта функция не использует данное поле.

Рис. 4.15 Исследование работы 06h при изменении адреса драйвера в Списке Списков

Изменений в работе функции 3fh также не возникает (см. Рис. 4.16).

Рис. 4.16 Исследование работы 3fh при изменении адреса драйвера в Списке Списков.

Попробуем теперь удалить драйвер из цепочки и изменить адрес драйвера в таблице SFT. Функция 06h теперь работает через драйвер консоли MS-DOS, что и видно на Рис. 4.17. Теперь посмотрим, как реагирует на изменения функция 3fh. Как видно на Рис. 4.18 функция 3fh продолжает работать через заменяющий драйвер консоли, однако следует отметить, что ввод осуществляется через драйвер консоли MS-DOS, так как на счетчик ввода остался в нуле, в то время как уже введено 5 символов.

Рис. 4.17 Исследование работы 06h при изменении адреса драйвера в SFT

Рис. 4.18 Исследование работы 3fh при изменении адреса драйвера в SFT

Теперь изменим указатели на драйвер в Списке Списков и таблице SFT.

Как видим на Рис. 4.19 теперь и функция 3fh работает через драйвер консоли MS-DOS. Значит, для полного переключения драйвера консоли необходимо менять указатели и в Списке Списков, и в таблице SFT.

Рис. 4.19 Исследование работы 3fh при изменении адреса драйвера в SFT и в Списке Списков

Проанализируем полученные результаты. Как известно, работать с файлами через дескрипторы намного удобнее, поэтому многие функции в DOS переписывались от версии к версии с целью увеличения быстродействия, изменения алгоритмов, унификации и т.д. Это привело к тому, что простейшие функции ввода-вывода DOS стали работать через дескриптор консоли. Отдельно стоит отметить работу функции 3fh int 21h. На основании вышеприведенных исследований данная функция осуществляет ввод через дескриптор файла консоли, а вывод через указатель на драйвер в Списке Списков (счетчик ввода справа равен 0). Этим объясняется поведение функции при закрытии драйвера на вывод, когда функция продолжала выводить символы (более подробно организацию закрытия/открытия драйвера рассмотрим ниже). Получается, что данная функция обращается только к дескриптору файла консоли (0-й), так же надо помнить о том, что функция 3fh ведет себя так, только в случае работы с консолью.

Рассмотрим механизм закрытия/открытия драйвера. Драйвер можно закрыть только функцией 3Eh int 21h, при этом в bx загружается номер дескриптора (0 и 1). На Рис. 4.20 изображен дамп DFCB блока файла консоли, черным цветом выделено поле счетчика дескрипторов связанных с файлом консоли.

Рис. 4.20 Дамп DFCB блока файла консоли

Теперь закроем драйвер на вывод. На Рис. 4.21видно, что количество связанных дескрипторов уменьшилось на 1. Это говорит о том, что дескриптор 0 - ничем не отличается от обычного дескриптора файла. При любой попытке обратится к 0 дескриптору, например, функцией дублирования дескрипторов, возвращается взведенный флаг CF и номер ошибки ax= 0006h - неверный дескриптор.

Рис. 4.21 Дамп DFCB блока файла консоли после закрытия драйвера на вывод

Закроем драйвер на ввод. На Рис. 4.22 видно, что количество связанных дескрипторов уменьшилось на 1. При попытке обращения к файлу консоли через 0-й или 1-й дескриптор базовые функции ввода-вывода DOS в большинстве случаев зависают. Например, функция 06h на Рис. 4.14 возвратила символ, код которого 06 - код ошибки при обращении к дескриптору “неверный дескриптор”.

Рис. 4.22 Дамп DFCB блока файла консоли после закрытия драйвера на ввод

При выходе из программы command.com восстанавливает закрытые дескрипторы, как это делается при переназначении ввода (с точки зрения command.com изменение стандартных дескрипторов - переназначение ввода).

Так же при переключении в бинарный режим в DFCB-блоке изменяется слово статуса IOCTL . На Рис. 4.23 дамп DFCB-блока файла драйвера в символьном режиме.

Рис. 4.23 Дамп DFCB-блока файла консоли в символьном режиме

После перевода драйвера в бинарный режим изменился 6-й бит слова атрибутов IOCTL. Рис. 4.24 дамп памяти DFCB-блока файла консоли в бинарном режиме.

Рис. 4.24 Дамп DFCB-блока файла консоли в бинарном режиме

Замена функций 06h, 0ch и 3fh прерывания int 21h

В тестовой программе №2 промоделированы функции 06h, 0ch и 3fh прерывания 21h. В режиме подмены 21 прерывания вызовы к этому прерыванию обрабатываются программой, если номер функции отличается от промоделированных, то управление передается оригинальному прерыванию DOS. Процедура моделирования функций состоит из трех частей: моделирование функции 06h, функции 0ch и функции 3fh.

Как известно прерывание это процедура, которая вызывается при выполнении команды int <номер прерывания>, а также при возникновении аппаратного прерывания. Адреса вызова этих процедур записаны в таблице векторов прерываний, которая расположена в сегменте 0000h. Подмена прерывания сводится к замене адреса прерывания DOS в векторной таблице прерываний на адрес обработчика прерывания в программе. Подменить прерывание можно двумя способами:

- используя функции DOS 25h - изменить адрес обработчика прерывания, 35h - получить адрес обработчика прерывания;

- методом прямой замены адреса обработчика прерывания в таблице векторов.

В тесте №2 реализован второй способ, как наиболее наглядный.

Алгоритм работы функции 06h приведен на Рис. 4.25. При вызове функции 06h int 21h формируется запрос на неразрушающий ввод, если символ не готов взводится флаг ZF и прерывание завершает свою работу.

Функция 0сh работает очень просто. Ее алгоритм приведен на Рис. 4.26. Фактически это процедура вызова команды драйвера FLUSH_INPUT.

Рис. 4.25 Алгоритм функции 06h

Рис. 4.26 Алгоритм функции 0ch

На Рис. 4.27 изображен алгоритм работы функции 3fh. В заменяющем прерывании, аналогично оригинальному, запись ведется в системный буфер. По нажатию клавиши Enter данные из системного буфера переписываются в пользовательский. В системный буфер нельзя ввести более 127 символов, при превышении этого числа звучит звуковой сигнал. Так же расширенные клавиши игнорируются. В бинарном режиме функция игнорирует системный буфер, чтение происходит за одно обращение к драйверу и без эха на экран. Определить режим ASCII/BIN режима драйвера можно по слову статуса IOCTL в DFCB-блоке консоли.

Рис. 4.27 Алгоритм функции 3fh

5. Разработка программы формирования списка драйверов (test3)

Назначение программы

Программа формирования списка драйверов предоставляет возможность проверить установку замещающего драйвера, а также исследовать последовательность загрузки драйверов в системе. Также эта программа дает возможность переключить драйвер консоли с замещающего на драйвер MS-DOS и отключить драйвер консоли.

Разработка схемы алгоритма программы

Алгоритм процедуры вывода списка драйверов изображен на Рис. 5.1

Рис. 5.1 Алгоритм процедуры вывода списка драйверов

Драйверы в системе скреплены в цепочку, поэтому чтобы найти драйвер в системе нужно просматривать драйвера по цепочке, пока не встретится необходимый драйвер.

Анализ результатов работы программы

Работа программы состоит из 3 этапов:

- Переключение вывода на консоль через драйвер MS-DOS

- удаление драйвера консоли MS-DOS из цепочки драйверов

- Изменение внутренних переменных MS-DOS, которые обеспечивают работу функций консоли DOS.

Сначала программа выводит список драйверов установленных в системе. На Рис. 5.2 изображен список драйверов в системе. В правой части экрана видно счетчики обращения к заменяющему драйверу.

Рис. 5.2 Список драйверов установленных в системе (перед первым этапом)

На первом этапе ввод-вывод переключается на резидентный драйвер консоли MS-DOS. Как видим на Рис. 5.3 заменяющего драйвера нет в списке, а также вывод ведется через резидентный драйвер MS-DOS (справа нет счетчиков).

Рис. 5.3 Экран тестовой программы № 3. Этап 1.

На этапе 2 резидентный драйвер MS-DOS удаляется из цепочки драйверов, но это не влияет на ввод-вывод. MS-DOS использует вышеприведенную таблицу SFT для доступа к драйверу. На рис. 5.4 в цепочке нет драйвера консоли, но вывод продолжается (вывод таблицы реализован с помощью функции DOS 09h int 21h).

Рис. 5.4 Экран тестовой программы № 3. Этап 2.

На этапе 3 будет испорчен адрес драйвера консоли в Списке Списков, что приведет к зависанию компьютера. Этот этап иллюстрирует, что при вводе-выводе DOS не пользуется цепочкой драйверов для поиска драйвера консоли, а берет его из Списка Списков.

Список литературы

1.Фролов А.,Фролов Г.Библиотека системного программиста, том 18, MS-DOS для програмиста, М.: Диалог-МИФИ, 1995, 254 с.

2. Зубков С.В. Ассемблер для DOS, Windows и UNIX, ДМК Пресс, 1999

Приложение 1.

Листинг программы драйвера

public interr,strateg

;

cseg segment para 'code'

console proc far

ASSUME cs:cseg,es:cseg,ds:cseg

rh struc ;Фиксированная структура заголовка

rh_len db ? ;Длина пакета

rh_unit db ? ;Номер устройства (блоковые)

rh_cmd db ? ;Команда драйвера устройства

rh_status dw ? ;возвращается драйвером

rh_res1 dd ? ;Зарезервировано

rh_res2 dd ? ;Зарезервировано

rh ends

;

rh0 struc ;Заголовок запроса для команды 0

rh0_rh db size rh dup (?) ;фиксированная часть

rh0_nunits db ? ;Число устройств в группе (блоковые)

rh0_brk_ofs dw ? ;Смещение для конца

rh0_brk_seg dw ? ;Сегмент для конца

rh0_bpb_tbo dw ? ;Смещение указателя массива ВРВ

rh0_bpb_tbs dw ? ;Сегмент указателя массива ВРВ

rh0_dn_itr db ? ;Первый доступный накопитель (DOS 3+)

rh0 ends

;

rh4 struc ;3аголовок запроса для команды 4

rh4_rh db size rh dup (?) ;фиксированная часть

rh4_nedla db ? ;Дескриптор носителя из DPB

rh4_buf_ofs dw ? ;Смещение DTA

rh4_buf_seg dw ? ;Сегмент DTA

rh4_count dw ? ;Счетчик передачи (секторов для

;блоковых, байтов для символьных)

rh4_start dw ? ;Начальный сектор (блоковые)

rh4 ends

;

rh5 struc ;Заголовок запроса для команды 5

rh5_rh db size rh dup (?) ;Фиксированная часть

rh5_return db ? ;Возвращаемый символ

rh5 ends

;

rh7 struc ;Заголовок запроса для команды 7

rh7_len db ? ;Длина пакета

rh7_unlt db ? ;Номер устройства (блоковые)

rh7_cmd db ? ;Команда драйвера устройства

rh7_status dw ? ;Возвращается драйвером

rh7_res1 dd ? ;Зарезервировано

rh7_res2 dd ? ;3арезервировано

rh7 ends

;

rh8 struc ;3аголовок запроса для команды 8

rh8_rh db size rh dup (?) ;Фиксированная часть

rh8_media db ? ;Дескриптор носителя из DPB

rh8_buf_ofs dw ? ;Смещение DTA

rh8_buf_seg dw ? ;Сегмент DTA

rh8_count dw ? ;Счетчик передачи (секторов для

;блоковых, байтов для символьных)

rh8_start dw ? ;Начальный сектор (блоковые)

rh8 ends

;

rh9 struc ;Заголовок-запроса для команды 9

rh9_rh db size rh dup (?) ;Фиксированная часть

rh9_medla db ? ;Дескриптор носителя из DPB

rh9_buf_of dw ? ;Смещение DTA

rh9_buf_seg dw ? ;Сегмент DTA

rh9_count dw ? ;Счетчик передачи (секторов для

;блоковых, байтов для симгольных)

rh9_start dw ? ;Начальный сектор (блоковые)

rh9 ends

;

begin:

;

next_dev dd -1

attribute dw 8003h

strategy dw dev_strategy

interrupt dw dev_interrupt

dev_name db 'CON '

;

rh_ofs dw ?

rh_seg dw ?

sav db 0

counter label word

initc dw 0

checkmc dw 0

make_BPBc dw 0

ioctl_inc dw 0

input_datac dw 0

nondest_inc dw 0

inpstatuc dw 0

flushinc dw 0

output_datac dw 0

outverifyc dw 0

outstatc dw 0

flushoutc dw 0

ioctl_outc dw 0

outstrings label byte

inits db 'inits: '

checkms db 'checkms: '

make_BPBs db 'make_BPBs: '

ioctl_ins db 'ioctl_ins: '

input_datas db 'input_datas: '

nondest_ins db 'nondest_ins: '

inpstatus db 'inpstatus: '

flushins db 'flushins: '

output_datas db 'output_datas:'

outverifys db 'outverifys: '

outstat db 'outstat: '

flushouts db 'flushouts: '

ioctl_outs db 'ioctl_outs: '

countstr db 4 dup(?) ;для числа

;

;***************************************************

;* ПРОЦЕДУРА СТРАТЕГИЯ

;***************************************************

strateg proc far

;

dev_strategy:

mov cs:rh_seg,es

mov cs:rh_ofs,bx

ret

endp

;

interr proc far

dev_interrupt:

cld

push ds

push es

push ax

push bx

push cx

push dx

push di

push si

mov ax,cs:rh_seg

mov es,ax

mov bx,cs:rh_ofs

mov al,es:[bx].rh_cmd

rol al,1

lea di,cmdtab

mov ah,0

add di,ax

jmp cs:word ptr [di]

cmdtab label byte

dw INITIALIZATION ;Инициализация

dw MEDIA_CHECK ;Контроль носителя (блоковые)

dw GET_BPB ;Получение ВРВ

dw IOCTL_INPUT ;IOCTL-BBOД

dw INPUT ;Ввод

dw ND_INPUT ;Неразрушающий ввод

dw INPUT_STATUS ;Состояние ввода

dw INPUT_FLUSH ;Очистка ввода

dw OUTPUT ;Вывод

dw OUTPUT_VERIFY ;Вывод с контролем

dw OUTPUT_STATUS ;Состояние вывода

dw OUTPUT_FLUSH ;Очистка вывода

dw IOCTL_OUTPUT ;IOCTL-вывод

dw OPEN ;Открытие устройства

dw CLOSE ;3акрытие устройства

dw REMOVABLE ;Сменный носитель

outwtohex proc

push bp

mov bp,sp

push cx bx dx

word2hex EQU [bp+4]

mov cx,4

mov bx,word2hex

c2: mov dx,bx

and dx,0F000h

shr dx,4

cmp dx,0a00h

jae add_37h

add dh,30h

cont:

mov cs:[si],dh

inc si

shl bx,4

loop c2

sub si,4

pop dx bx cx bp

ret 2

add_37h:add dh,37h

jmp cont

outwtohex endp

;------------------------------------------------------

WriteStr proc near

mov ax,0B800h

mov es,ax

mov ah,07h

c:

mov al,cs:[si]

mov es:[di],ax

inc si

add di,2

loop c

ret

WriteStr endp

;------------------------------------------------------

getDRV proc near

push bx si di cx ax

lea bx,counter

lea si,outstrings

mov di,0

mov cx,13

loopcounters:

push cx

mov cx,13

add di,126

call writeStr

push si

lea si,countstr

mov ax,[bx]

push ax

call outwtohex

mov cx,4

call writeStr

pop si

add bx,2

pop cx

loop loopcounters

pop ax cx di si bx

ret

getDRV endp

;

; Команда 0 - Инициализация

initialization:

; call initial ;Вывести сообщение

lea ax,initial ;Остановить адрес конца

mov es:[bx].rh0_brk_ofs,ax ;Сохранить смещение

mov es:[bx].rh0_brk_seg,cs ;Сохранить сегмент

mov ax,initc

inc ax

mov initc,ax

jmp done ;Остановить СДЕЛАНО и выйти

;

;Команда 1 - Контроль носителя

media_check:

mov ax,checkmc

inc ax

mov checkmc,ax

jmp done ;Установить бит СДЕЛАНО и выйти

;Команда 2 - Получение ВРВ

get_bpb:

mov ax,make_BPBc

inc ax

mov make_BPBc,ax

jmp done ;Установить бит СДЕЛАНО и выйти

;Команда З - Ввод IOCTL

IOCTL_input:

mov ax,ioctl_inc

inc ax

mov ioctl_inc,ax

jmp unk ;Установить бит ОШИБКА и выйти

;Команда 4 - Ввод

input:

mov ax,input_datac

inc ax

mov input_datac,ax

mov cx,es:[bx].rh4_count ;3агрузить счетчик ввода

mov di,es:[bx].rh4_buf_ofs ;3агрузить смещение

mov ax,es:[bx].rh4_buf_seg ;Загрузить сегмент

mov es,ax ;Передать сегмент в ES

read1:

mov ax,0 ;Сбросить АХ

xchg al,sav ;Взять сохраненный символ

cmp al,0 ;0н равен 0 ?

jne read3 ;Нет - возвратить его

read2:

mov ah,0 ;0бслуживание считывания

int 16h ;Вызов клавиатуры BIOS

cmp ax,0 ;Клавиша равна 0 ?

jz read2 ;Да, взять другой символ

cmp al,0 ;Это расширенная клавиша ?

jne read3 ;Нет-возвратить ее

mov sav,ah ;Сохраноть скэн-код

read3:

mov es:[di],al ;Сохранить значение в буфере

inc di ;Продвинуть указатель

push cx ;Сохранить СХ

pop cx ;Восстановить СХ

loop read1 ;Продолжать до счетчика = 0

mov ax,cs:rh_seg ;восстановить регистр ES

mov es,ax ;из rh_seg

mov bx,cs:rh_ofs ;Восстановить регистр ВХ

jmp done ;Установить бит СДЕЛАНО и выйти

;Команда 5 - Неразрушающий ввод

nd_input:

mov ax,nondest_inc

inc ax

mov nondest_inc,ax

mov al,sav ;Взять сохраненный символ

cmp al,0 ;0н равен 0?

jne nd1 ;Нет - возвратить его в DOS

mov ah,1 ;Обслуживание - контроль состояния

int 16h ;Вызов клавиатуры BIOS

jz GObusy ;При ZF = 1 символа в буфере нет

cmp ax,0 ;Клавиша - 0?

jne nd1 ;Нет - возвратить ее в DOS

mov ah,0 ;Обслуживание - считывание

int 16h ;Выэов клавиатуры BIOS

jmp nd_input ;Проверять вновь

gobusy: jmp busy

nd1:

mov es:[bx].rh5_return,al ;возвратить клавишу в DOS

jmp done ;Остановить бит СДЕЛАНО и выйти

;команда 6 - Состояние ввода

input_status:

mov ax,inpstatuc

inc ax

mov inpstatuc,ax

jmp done ;Установить бит СДЕЛАНО и выйти

;Команда 7 - Очистка ввода

input_flush:

mov ax,flushinc

inc ax

mov flushinc,ax

mov sav,0 ;Сбросить сохраненный символ

if11:

mov ah,1 ;Обслуживание - контроль состояния

int 16h ;Вызов клавиатуры BIOS

jz done ;При ZF = 1 буфер пустой

mov ah,0 ;Обслуживание - считывание

int 16h ;Вызов клавиатуры BIOS

jmp if11 ;Повторять до опустошения

;Команда 8 - Вывод

output:

mov ax,output_datac

inc ax

mov output_datac,ax

mov cx,es:[bx].rh8_count ;Взять счетчик вывода

mov di,es:[bx].rh8_buf_ofs ;Загрузить смещение

mov ax,es:[bx].rh8_buf_seg ;Загрузить сегмент

mov es,ax ;в регистр ES

mov bx,0 ;Сбросить ВХ

out1:

mov al,es:[di] ;Взять выводимый символ

inc di ;Продвинуть указатель

mov ah,0eh ;Обслуживание - запись как TTY

int 10h ;Вызов экрана BIOS

loop out1 ;Повторять до исчерпания счетчика

mov ax,cs:rh_seg ;Восстановить в регистре ES

mov es,ax ;сегмент заголовка запроса

mov bx,cs:rh_ofs ;восстановить регистр ВХ

jmp done ;Установить бит СДЕЛАНО и выйти

;Команда 9 - Вывод с контролем

output_verify:

mov ax,outverifyc

inc ax

mov outverifyc,ax

jmp output ;Аналогично команде вывода

;Команда 10 - Состояние вывода

output_status:

mov ax,outstatc

inc ax

mov outstatc,ax

jmp done ;Установить бит СДЕЛАНО и выйти

;Команда 11 - Очистка вывода

output_flush:

mov ax,flushoutc

inc ax

mov flushoutc,ax

jmp done ;Установить бит СДЕЛАНО и выйти

;Команда 12 - IOCTL-вывод

ioctl_output:

mov ax,ioctl_outc

inc ax

mov ioctl_outc,ax

jmp unk ;Установить бит ОШИБКА и выйти

;Команда 13 - Открытие

open:

jmp done ;Установить бит СДЕЛАНО и выйти

;Команда 14 - Закрытие

close:

jmp done ;Остановить бит СДЕЛАНО и выйти

;Команда 15 - Сменный носитель

removable:

jmp unk ;Остановить бит ОШИБКА и выйти

;Команда 16 - Вывод до занятости

output_busy:

jmp unk ;Установить бит ОШИБКА и выйти

;

unk:

or es:[bx].rh_status,8003h ;Остановить бит и код ошибки

jmp done ;Установить бит СДЕЛАНО и выйти

busy:

or es:[bx].rh_status,0200h ;Установить бит ЗАНЯТ

done:

or es:[bx].rh_status,0100h ;Установить бит СДЕЛАНО

call getDRV

pop si di dx cx bx ax es ds ;восстановить все регистры

ret ;Возврат в DOS

endp

;******************************************************

;* КОНЕЦ ПРОГРАММЫ

;******************************************************

;

initial proc near ;Вывод сообщения на консоль

lea dx,msg ;Адрес выводимого сообщения

mov ah,09h ;Вывод на экран

int 21h ;Вызов вывода строки

ret ;Возврат

initial endp

;

msg db 'Driver module initialization called',13,10,'$'

;

console endp ;Конец процедуры CONSOLE

cseg ends ;Конец сегмента CSEG

end begin ;Конец программы

Приложение 2

Листинг программы отладки драйвера

{$D+}

{$L+}

program test1;

uses crt;

type

res = array [1..8] of byte;

theader = record

size : byte;

unitN: byte;

cmd : byte;

status:word;

reserv: res;

end;

tzapros = record

header : theader;

n_dev : byte;

end_addr_off: word;

end_addr_seg: word;

parm_off : word;

parm_seg : word;

drive : byte;

msg_flag:byte;

end;

var

zapros : tzapros;

buf : array [1..64] of char;

bufferkbd : string [82];

i : byte;

buff:word;

choice: char;

{$L drv1.obj}

{$F+}

procedure strateg; external;

procedure interr; external;

{$F-}

procedure w2h(hexword:integer);

var

work,i,shift : word;

begin

for i:=1 to 2 do

begin

work:=hexword;

work:=work and 240;

work:=work shr 4;

if work>9 then work:=work+ord('A')- 10

else work:=work+ord('0');

write(char(work));

work:=hexword;

work:=work and 15;

if work>9 then work:=work+ord('A')- 10

else work:=work+ord('0');

write(char(work));

hexword:=hexword shr 8;

end;

write (' ');

end;

procedure outheader;

begin

writeln ('Header structure:');

writeln (' size: ',zapros.header.size);

writeln (' UnitN: ',zapros.header.unitn);

writeln (' command: ',zapros.header.cmd);

write (' Status: ');

w2h(zapros.header.status);

writeln;

end;

procedure delayproc;

begin

asm

push ax

push dx

push cx

push bx

mov ah,00h

int 1ah

mov bx,dx

add bx,91d

@c:

mov ah,0h

int 1ah

cmp dx,bx

jl @c

pop bx

pop cx

pop dx

pop ax

end;

end;

procedure outreq_4;

begin

zapros.header.status:=0;

writeln ('DPB:',zapros.n_dev);

write ('Offset DTA:');

w2h(zapros.end_addr_off);

writeln;

write ('Segment DTA:');

w2h(zapros.end_addr_seg);

writeln;

writeln ('counter:',zapros.parm_off);

end;

procedure testinit;

begin

zapros.header.status:=0;

zapros.header.size:=24;

zapros.header.cmd:=0;

outheader;

writeln ('Initialization called ');

asm

push ds;

pop es;

lea bx,zapros;

end;

strateg;

interr;

outheader;

write ('Segment of end:');

w2h(zapros.end_addr_seg);

writeln;

write ('Offset of end:');

w2h(zapros.end_addr_off);

writeln;

readln;

end;

procedure testread;

begin

writeln ('Testing function 4: READ');

write('Forming header: ');

zapros.header.size:=30;

zapros.header.cmd:=4;

zapros.parm_off:=5;

zapros.end_addr_off:=ofs(buf);

zapros.end_addr_seg:=seg(buf);

writeln('done');

outheader;

outreq_4;

readln;

writeln ('Enter 5 characters! ');

asm

push ds;

pop es;

lea bx,zapros;

end;

strateg;

interr;

writeln;

writeln('Was entered: ');

for i:=1 to 5 do

write(buf[i]);

readln;

end;

procedure dispkeyb;

var

i,head_b,tail_b,work:word;

begin

asm

push ax

push bx

push es

mov bx,40h

mov es,bx

mov bx,1ah

mov ax,es:[bx]

mov head_b,ax

mov ax,es:[bx+2]

mov tail_b,ax

pop es

pop bx

pop ax

end;

i:=0;

while i<=32 do

begin

asm

push bx

push es

push ax

mov bx,40h

mov es,bx

mov bx,1eh

add bx,i

mov ax,es:[bx]

mov work,ax

pop ax

pop es

pop bx

end;

if (head_b - 30)=i then write (' H ');

if (tail_b - 30)=i then write (' T ');

w2h(work);

i:=i+2;

end;

end;

procedure testflush;

begin

writeln('Testing command 7: FLUSH');

write ('Forming request for command: ');

zapros.header.size:=13;

zapros.header.cmd:=7;

writeln ('done');

outheader;

readln;

dispkeyb;

delayproc;

writeln;

dispkeyb;

delayproc;

writeln;

writeln ('Calling driver.');

asm

push ds;

pop es;

lea bx,zapros;

end;

strateg;

interr;

dispkeyb;

writeln;

writeln ('Keyboard buffer is empty!');

readln;

end;

begin

while true do

begin

clrscr;

writeln ('Выберите режим: ');

writeln ('1. Тестирование команды инициализации');

writeln ('2. Тестирование команды чтения');

writeln ('3. Тестирование очистки ввода');

readln(choice);

clrscr;

case choice of

'1' : testinit;

'2' : testread;

'3' : testflush;

else halt(0);

end;

clrscr;

end;

end.

Приложение 3.

Листинг программы исследования драйвера

; Вывод 0ah int 10h

stacks segment 'stack' stack

db 128 dup (?)

stacks ends

datseg segment

intishooked db 13,10,'Interrupt is hooked!!!','$'


Подобные документы

  • Архитектура ввода/вывода Windows NT. Внутренняя организация шины USB. Сущностная характеристика драйверной модели WDM. Точки входа разрабатываемого драйвера, размещение кода в памяти, установка драйвера в системе. Реализация кода драйвера на языке C.

    курсовая работа [1,2 M], добавлен 27.09.2014

  • Повышение быстродействия операционной системы. Разработка драйверов для средств хранения данных, управление работой устройства командами PnP. Создание, настройка параметров и установка классового драйвера виртуального диска, его структура и свойства.

    курсовая работа [163,2 K], добавлен 18.06.2009

  • Анализ задания и разработка алгоритма. Основные принципы создания программы. Схема взаимодействия процессов Process 1 и Process 4, в режиме задачи и в режиме ядра. Листинг программы и ее тестирование. Результат работы и выполнения программы в консоли.

    контрольная работа [395,9 K], добавлен 18.09.2010

  • Разработка драйвера под Linux, отслеживающего выделение и освобождение процессами виртуальной памяти и выделение физических страниц при страничных отказах. Компиляция драйвера и работа с ним. Экспериментальная проверка работоспособности драйвера.

    курсовая работа [43,5 K], добавлен 18.06.2009

  • Механизмы взаимодействия драйвера режима ядра и пользовательского приложения: многослойная драйверная архитектура, алгоритм сокрытия данных, взаимодействие драйвера и приложения, пользовательский интерфейс программы фильтрации доступа к файлам.

    курсовая работа [1023,3 K], добавлен 23.06.2009

  • Описание принципа работы драйвера. Установка и регистрация драйвера. Назначение и возможности утилиты TestTerminals.exe. Использование редактора форм. Создание форм с помощью редактора задач. Последовательность выполнения операций и обработок данных.

    курсовая работа [843,6 K], добавлен 09.11.2011

  • Введение в API-программирование. Структура API-программ. Организация ввода-вывода в консольном приложении Windows. Организация низкоуровнего консольного ввода-вывода. Расширенная поддержка клавиатуры в консоли. Поддержка работы с мышью в консоли.

    курсовая работа [91,0 K], добавлен 10.02.2015

  • Использование драйвера режима ядра и управляющего приложения для создания системных потоков. Имитация обработки данных и организация задержек. Разработка драйвера на языке C++. Конфигурация тестового стенда. Точность изменения задержек и работы таймера.

    курсовая работа [182,4 K], добавлен 24.06.2009

  • Аналитический обзор существующих параллельных интерфейсов. Разработка лабораторного стенда и алгоритмов подпрограмм обмена информацией. Создание программ драйвера ИРПР. Команды микропроцессора, алгоритмы подпрограмм инициализации, ввода и вывода символа.

    курсовая работа [255,2 K], добавлен 10.07.2017

  • Разработка программного обеспечения для упрощения буквенно-цифрового ввода при невозможности использовать функционал стандартной буквенной клавиатуры. Классификация и установка драйверов. Выбор языка и среды программирования. Пользовательский интерфейс.

    курсовая работа [183,0 K], добавлен 12.03.2013

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.