Введение
Данная курсовая работа представляет из себя драйвер символьного устройства. После инициализации в системе появляется новое устройство $rot13, на которое можно посылать данные, например:
copy file.txt $rot13
Драйвер шифрует данные, сдвигая каждую букву английского алфавита на 13 позиций, и выдает результат на экран.
Операционная система – MS DOS, Windows’95, 98.
Драйвер полностью написан на языке ассемблера.
Минимальные требования для работы: Процессор – 8086. Оперативная память – 64 Кб.
Компиляция проводилась пакетом MASM.
Пояснительная записка
Драйверы устройств - это часть операционной системы ПК, задача которой состоит в управлении устройствами и связью между ними. Они находятся в операционной системе на самом близком к аппаратным средствам уровне и обеспечивают аппаратно-независимую работу на других уровнях. Преимущества такого подхода проявляются при адаптации операционной системы к различным компьютерам. Не требуется изменять всю систему, достаточно только изменить драйверы.
В первых операционных системах драйверы являлись составной частью кода этих систем. Это приводило к тому, что изменить или усовершенствовать эти программы в соответствии с характеристиками новых устройств было очень трудно, а то и невозможно. Гибкая концепция драйверов устройств была введена в DOS версии 2.0. У пользователя появилась возможность адаптировать самые экзотические устройства, совместимые с ПК к работе с DOS.
Взаимодействие DOS и драйвера устройства осуществляется через сравнительно простые функции и структуры данных, поэтому программист, пишущий на языке ассемблера, может самостоятельно разработать драйвер для работы устройства под управлением DOS. К сожалению, драйвер невозможно написать на языке более высокого уровня.
Работая над кодом драйвера, следует придерживаться тех же правил, что и при разработке COM-программ (нет прямого доступа к сегменту). Разница состоит в том, что тело драйвера начинается со смещения 0h, а не 100h.
При загрузке DOS автоматически загружаются и приводятся в готовность драйверы NUL, CON, AUX, PRN, а также, если нужно, драйверы дисководов. Они располагаются в памяти последовательно и связаны друг с другом. Если пользователь хочет установить дополнительно еще какой-нибудь драйвер, он должен проинформировать об этом DOS через файл CONFIG.SYS. Этот текстовый файл содержит информацию, которая нужна DOS для конфигурирования системы. Содержимое файла CONFIG.SYS считывается и интерпретируется во время процесса загрузки после подключения стандартных драйверов. Если DOS обнаруживает команду DEVICE = , значит, нужно подключить еще один драйвер. Справа от знака равенства в этой команде указывается имя драйвера и, возможно, устройство и маршрут.
Например, подключение драйвера, написанного в этой курсовой работе, производится следующей строкой:
DEVICE=C:\ROT13.EXE
(здесь имеется в виду, что драйвер находится в корневом каталоге диска C:, то есть жесткого диска).
Новый драйвер добавляется в последовательность драйверов сразу за драйвером NUL (первым драйвером в цепочке).
Взаимодействие драйверов символьных устройств с клавиатурой, экраном, принтером, другими устройствами осуществляется посимвольно (побайтно). Драйверы блочных устройств могут пересылать целые последовательности символов при каждом вызове функции (доступ к дискам, жестким дискам и т.д.). Эти две группы драйверов отличаются подходами к реализации различных функций. В данной курсовой работе написан драйвер символьного устройства.
Несмотря на то, что драйверы могут существенно различаться по назначению, они имеют одинаковую структуру. Каждый драйвер имеет заголовок, подпрограмму стратегии и подпрограмму прерывания (имеется в виду не то прерывание, о котором вы читали до этого момента).
Заголовок. В начале каждого драйвера устройства размещается заголовок, который содержит информацию, необходимую DOS для установки драйвера.
Первые два поля указывают на следующий драйвер (это сегментный адрес и смещение) в цепочке драйверов устройств. Ячейки памяти под эти поля должны быть зарезервированы программистом, а заполнит их DOS при установке драйвера в системе. Следующим полем в заголовке является слово-атрибут. Атрибут описывает драйвер устройства и, среди прочего, сообщает DOS о том, какого типа этот драйвер - блочный или символьный.
Структура заголовка драйвера:
┌───┬────────────────────────────────────┬───────┐
│00h│Смещение следующего драйвера │1 слово│
├───┼────────────────────────────────────┼───────┤
│02h│Сегментный адрес следующего драйвера│1 слово│
├───┼────────────────────────────────────┼───────┤
│04h│Атрибут устройства │1 слово│
├───┼────────────────────────────────────┼───────┤
│06h│Смещение подпрограммы стратегии │1 слово│
├───┼────────────────────────────────────┼───────┤
│08h│Смещение подпрограммы прерываний │1 слово│
├───┼────────────────────────────────────┼───────┤
│0Ah│Имя драйвера, если символьный, или │8 байт │
│ │количество устройств, если блочный. │ │
└───┴────────────────────────────────────┴───────┘
Структура атрибута устройства:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
┌─┬─┬──┬──┬──┬──┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ бит
│ │ │ │ X│ │ X│X│X│X│X│X│X│ │ │ │ │ ──── 1=текущее стандартное
└┬┴┬┴┬─┴──┴┬─┴──┴─┴─┴─┴─┴─┴─┴┬┴┬┴┬┴─┘ устройство вывода
│ │ │ │ │ │ └──────── 1=текущее стандартное
│ │ │ │ │ │ устройство ввода
│ │ │ │ │ └────────── 1=текущее устройство "часы"
│ │ │ │ └──────────── 1=текущее устройство NUL
│ │ │ └────────────────────────────── 1=обнаружено изменение
│ │ │ носителя
│ │ │ ┌ 1=формат не IBM
│ │ │ │ (блочный драйвер)
│ │ └───────────────────────────────────┤
│ │ └ 1=вывод до команды
│ │ (символьный драйвер)
│ └────────────────────────────────────── 1=поддержка IOCTL
└──────────────────────────────────────── 0=блочный драйвер
1=символьный драйвер
Блочный драйвер использует биты только с 11-го по 15-й. Бит IOCTL сообщает DOS о том, поддерживает ли драйвер функцию IOCTL. Бит 11 является значащим начиная с DOS версии 3.0, а в ранних версиях должен быть равен нулю. Блочный драйвер сообщает также о том, распознается ли замена носителя (например, гибкого диска) в поддерживаемом устройстве. Если соответствующий бит равен 1, значит, драйвер должен поддерживать некоторые дополнительные функции.
Следующие два поля содержат смещение подпрограмм стратегии и прерывания. Последнее поле содержит имя драйвера устройства. Если длина имени менее восьми символов, оставшиеся байты заполняются пробелами (ASCII-код 32). Если же этот драйвер блочного устройства, то первый байт этого поля содержит количество логических устройств, поддерживаемых драйвером. Остальные семь байт этого поля не используются и содержат значение 0.
Подпрограмма стратегии. DOS вызывает подпрограмму стратегии в первый раз при инициализации драйвера, а затем повторно перед каждым запросом на ввод/вывод, приходящим из подпрограммы прерывания. Адрес структуры данных, содержащей информацию об операции, которую следует выполнить, DOS передает подпрограмме стратегии в паре регистров ES:BX.
Указатель (двойное слово) на блок данных запоминается и управление сразу же возвращается DOS, которая вызывает подпрограмму прерывания драйвера, чтобы выполнить операцию. Заголовок запроса, адрес которого передается в подпрограмму стратегии, всегда состоит по меньшей мере из 13 байт и содержит информацию для драйвера о том, как выполнить предстоящую операцию. В зависимости от выполненных операций в конец заголовка запроса может быть добавлена дополнительная информация.
Структура заголовка запроса:
┌─────┬─────────────────────────────────┬─────────┐
│ 00h │Длина блока данных в байтах │ 1 слово │
├─────┼─────────────────────────────────┼─────────┤
│ 01h │Номер устройства │ 1 слово │
├─────┼─────────────────────────────────┼─────────┤
│ 02h │Код команды │ 1 слово │
├─────┼─────────────────────────────────┼─────────┤
│ 05h │Зарезервировано │ 8 байт │
├─────┼─────────────────────────────────┼─────────┤
│ 0Dh │Дескриптор носителя │ 1 байт │
├─────┼─────────────────────────────────┼─────────┤
│ 0Eh │Смещение буфера │ 1 слово │
├─────┼─────────────────────────────────┼─────────┤
│ 10h │Сегментный адрес буфера │ 1 слово │
├─────┼─────────────────────────────────┼─────────┤
│ 12h │Номер │ 1 слово │
├─────┼─────────────────────────────────┼─────────┤
│ 14h │Начальный сектор │ 8 байт │
└─────┴─────────────────────────────────┴─────────┘
DOS вызывает подпрограмму прерывания сразу же после вызова подпрограммы стратегии. Ее первой задачей является запоминание в стеке содержимого регистров процессора, которое будет изменяться различными функциями драйвера. После этого она достает из поля 3 заголовка запроса код команды и вызывает процедуру, соответствующую этому коду. По окончании процедуры подпрограмма прерывания заполняет поле состояния в заголовке запроса и восстанавливает значения регистров процессора. Последним шагом является возврат управления вызывающей функции DOS.
Поле состояния. Значение поля состояния показывает, было ли выполнение функции нормальным, или же при выполнении была зафиксирована ошибка. По этой причине каждая функция драйвера должна устанавливать бит DONE ("сделано" - бит 8) в поле состояния. Этот бит DONE должен быть установлен даже тогда, когда функция ничего не делает.
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
┌─┬─┬──┬──┬──┬──┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│ │X│ X│ X│ X│ X│ │ │ │ │ │ │ │ │ │ │
└┬┴─┴──┴──┴──┴──┴┬┴┬┴┬┴─┴─┴─┴─┴─┴─┴┬┘
│ │ │ └──────┬──────┘
┌┴─────────────┐ │ │ │
│0 = нормальное│ │ │ ┌──────┴─────────────────────────────────────┐
│ завершение│ │ │ │Код ошибки, если бит 15 равен 1 │
│1 = ошибка │ │ │ ├────────────────────────────────────────────┤
└──────────────┘ │ │ │0 = носитель защищен от записи │
┌──────────────┐ │ │ │1 = неизвестное устройство │
│1 = готово ├─┘ │ │2 = дисковод не готов │
└──────────────┘ │ │3 = неизвестная команда │
│ │4 = ошибка чтения (CRC-) │
┌──────────────┐ │ │5 = неверна длина блока данных (параметров) │
│1 = занято ├───┘ │6 = ошибка поиска │
└──────────────┘ │7 = неизвестный носитель │
│8 = сектор не найден │
│9 = бумага не вставлена в принтер │
│10= ошибка записи │
│11= ошибка чтения │
│12= общая ошибка │
│13= недопустимое изменение носителя │
└────────────────────────────────────────────┘