Команда XOR выполняет операцию логического (побитового) ИСКЛЮЧАЮЩЕГО ИЛИ над двумя операндами. Результат операции замещает первый операнд. Каждый бит результата устанавливается в 1, если соответствующие биты операндов различны, и сбрасывается в 0, если соответствующие биты операндов совпадают.
В качестве первого операнда можно указывать регистр (кроме сегментного) или ячейку памяти, в качестве второго - регистр (кроме сегментного), ячейку памяти или непосредственное значение, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами.
2 ОСОБЕННОСТИ НАПИСАНИЯ ДРАЙВЕРОВ
Драйверы устройств в DOS
Прикладные программы обычно никогда не используют уровень портов входа-выхода, а обращаются ко всем устройствам через средства операционной системы. DOS, в свою очередь, обращается к средствам BIOS, которые осуществляют взаимодействие на уровне портов со всеми стандартными устройствами. Фактически процедуры BIOS и выполняют функции драйверов устройств - программ, осуществляющих интерфейс между операционной системой и аппаратной частью компьютера. BIOS обычно лучше всего известно, как управлять устройствами, которые поставляются вместе с компьютером, но, если требуется подключить новое устройство, о котором BIOS ничего не знает, появляется необходимость в специально написанном загружаемом драйвере.
Драйверы устройств в DOS - исполняемые файлы со специальной структурой, которые загружаются на этапе запуска (при выполнении команд DEVICE или DEVICEHIGH файла config.sys) и становятся фактически частью системы. Драйвер всегда начинается с 18-байтного заголовка:
+00: 4 байта -дальний адрес следующего загружаемого драйвера DOS - так как в момент загрузки драйвер будет последним в цепочке, адрес должен быть равен 0FFFFh:0FFFFh
+04: 2 байта - атрибуты драйвера
+06: 2 байта - адрес процедуры стратегии
+08: 2 байта - адрес процедуры прерывания
+OAh: 8 байт - имя драйвера для символьных устройств (дополненное пробелами) для блочных устройств - байт по смещению OAli включает число устройств, поддерживаемых этим драйвером, а остальные байты могут содержать имя драйвера
Здесь следует заметить, что DOS поддерживает два типа драйверов - символьного и блочного устройств. Первый тип используется для любых устройств -клавиатуры, принтера, сети, а второй - только для устройств, на которых могут существовать файловые системы, то есть для дисководов, RAM-дисков, нестандартных жестких дисков, для доступа к разделам диска, занятым другими операционными системами, и т. д. Для работы с символьным устройством программа должна открыть его при помощи функции DOS «открыть файл или устройство», а для работы с блочным устройством - обратиться к соответствующему логическому диску.
Итак, код драйвера устройства представляет собой обычный код программы, как и в случае с СОМ-файлом, но в начале не надо размещать директиву org 100h для пропуска PSP. Можно также объединить драйвер и исполняемую программу, разместив в ЕХЕ-файле код драйвера с нулевым смещением от начала сегмента, а точку входа самой программы ниже.
При обращении к драйверу DOS сначала вызывает процедуру стратегии (адрес по смещению 06 в заголовке), передавая ей адрес буфера запроса, содержащий все параметры, передаваемые драйверу, а затем процедуру прерывания (адрес по смещению 08) без каких-либо параметров. Процедура стратегии должна сохранить адрес буфера запроса, а процедура прерывания - собственно выполнить все необходимые действия. Структура буфера запроса меняется в зависимости от типа команды, передаваемой драйверу, но структура его заголовка остается постоянной:
+00h: байт - длина буфера запроса (включая заголовок)
+01h: байт - номер устройства (для блочных устройств)
+02h: байт - код команды (00h - 19h)
+03h: 2 байта - слово состояния драйвера - должно быть заполнено драйвером
бит 15: произошла ошибка
биты 10-14: 00000b
бит 9: устройство занято
бит 8: команда обслужена
биты 7-0: код ошибки
00h: устройство защищено от записи
0lh: неизвестное устройство
02h: устройство не готово
03h: неизвестная команда
04h: ошибка CRC
05h: ошибка в буфере запроса
06h: ошибка поиска
07h: неизвестный носитель
08h: сектор не найден
09h: нет бумаги
0Ah: общая ошибка записи
0Вh: общая ошибка чтения
0Сh: общая ошибка
0Fh: неожиданная смена диска
+05h: 8 байт - зарезервировано
+0Dh: отсюда начинается область данных, отличающаяся для разных команд
Даже если драйвер не поддерживает запрошенную от него функцию, он обязательно должен установить бит 8 слова состояния в 1.
Символьные устройства
Драйвер символьного устройства должен содержать в поле атрибутов драйвера (смещение 04 в заголовке) единицу в самом старшем бите. Тогда остальные биты трактуются следующим образом:
бит 15: 1
бит 14: драйвер поддерживает функции чтения/записи IOCTL
бит 13: драйвер поддерживает функцию вывода до занятости
бит 12: 0
бит 11: драйвер поддерживает функции открыть/закрыть устройство
биты 10-8:000
бит 7: драйвер поддерживает функцию запроса поддержки IOCTL
бит 6: драйвер поддерживает обобщенный IOCTL
бит 5: 0
бит 4: драйвер поддерживает быстрый вывод (через INT 29h)
бит 3: драйвер устройства «часы»
бит 2: драйвер устройства NUL
бит 1: драйвер устройства STDOUT
бит 0: драйвер устройства STDIN
IOCTL - это большой набор функций (свыше пятидесяти), доступных как различные подфункции INT 21h АН = 44h и предназначенных для прямого взаимодействия с драйверами.
Рассмотрим драйвер, который вообще не обслуживает никакое устройство, реальное или виртуальное, а просто увеличивает размер буфера клавиатуры BIOS до 256 (или больше) символов. Этого можно было бы добиться обычной резидентной программой, но BIOS хранит в своей области данных только ближние адреса для этого 6yфepa, то есть смещения относительно сегментного адреса 0040h. Так как драйверы загружаются в память первыми, еще до командного интерпретатора, они обычно попадают в область линейных адресов 00400h -10400h, в то время как с резидентными программами этого может не получиться.
Драйвер, обрабатывающий только одну команду, команду инициализации драйвера 00h. Для нее буфер запроса выглядит следующим образом:
+00h: байт - 19h (длина буфера запроса)
+01h: байт - не используется
+02h: байт - 00 (код команды)
+03h: байт - слово состояния драйвера (заполняется драйвером)
+05h: 8 байт - не используется
+0Dh: байт - число обслуживаемых устройств (заполняется блочным драйвером)
+0Eh: 4 байта - на входе - конец доступной для драйвера памяти; на выходе -адрес первого байта из той части драйвера, которая не будет резидентной (чтобы выйти без инсталляции - здесь надо записать адрес первого байта)
+12Ь: 4 байта - на входе - адрес строки в CONFIG.SYS, загрузившей драйвер; на выходе - адрес массива ВРВ (для блочных драйверов)
+16h: байт - номер первого диска
+17h: 2 байта -сообщение об ошибке (0000h, если ошибки не было) - заполняется драйвером
Процедура инициализации может использовать функции DOS Olh – 0Ch, 25h, 30h и 35h.
Рассмотрим функции, которые должен поддерживать ROT13 — драйвер символьного устройства. ROT13 - это метод простой модификации английского текста, применяющийся в электронной почте, чтобы текст нельзя было прочитать сразу. Методика заключается в сдвиге каждой буквы латинского алфавита на 13 позиций (в любую сторону, так как всего 26 букв). Раскодирование, очевидно, выполняется такой же операцией. Когда драйвер загружен, команда DOS