Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2012 ЛР Ассемблер Архитектура ВС 6 семестр.doc
Скачиваний:
7
Добавлен:
03.05.2019
Размер:
454.66 Кб
Скачать

Xchg Обмен данными между операндами

Команда XCHG пересылает значение первого операнда во второй, а второго - в первый. В качестве операндов можно указывать регистр (кроме сегментного) или ячейку памяти, а в качестве второго операнда еще и непосредственное значе­ние, однако не допускается определять оба операнда одновременно как ячейки памяти. Операнды могут быть байтами или словами со знаком или без знака.

Xlat Табличная трансляция

Команда XLAT осуществляет выборку байта из таблицы. В регистре ВХ должен находиться относительный адрес таблицы, а в регистре AL - смещение в таблице к выбираемому байту (его индекс). Выбранный байт загружается в ре­гистр AL, замещая находившееся в нем смещение. Длина таблицы может дости­гать 256 байтов. Команда XLAT не имеет явных операндов, но требует предвари­тельной настройки регистров ВХ и AL.

Xor Логическое исключающее или

Команда 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

copy encrypt.txt rot13

приведет к тому, что текст из 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 атрибута)

+ODh: байт - категория устройства (01, 03, 05 = СОМ, CON, LPT)

00h - неизвестная категория

+0Eh: байт - код подфункции:

45h: установить число повторных попыток

65h: определить число повторных попыток

4Ah: выбрать кодовую страницу

6Ah: определить активную кодовую страницу

4Ch: начало подготовки кодовой страницы

4Dh: конец подготовки кодовой страницы

6Bh: получить список готовых кодовых страниц

5Fh: установить информацию о дисплее

7Fh: получить информацию о дисплее

+0Fh: 4 байта - не используются

+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 атрибута)

+ODh: байт - категория устройства:

08h: дисковое устройство

48h: дисковое устройство с FAT32

+OEh: код - подфункции:

40h: установить параметры

60h: прочитать параметры

41h: записать дорожку

42h: отформатировать и проверить дорожку

62h: проверить дорожку

46h: установить номер тома

66h: считать номер тома

47h: установить флаг доступа

67h: прочитать флаг доступа

68h: определить тип носителя (DOS 5.0+)

Драйверы устройств

В Windows, так же как и в DOS, существует еще один вид исполняемых фай­лов - драйверы устройств. Windows 3.хх и Windows 95 используют одну модель драйверов, Windows NT - другую, a Windows 98 - уже третью, хотя и во многом близкую к модели Windows NT. В Windows 3.хх/95 применяются два типа драйве­ров устройств - виртуальные драйверы (VxD), выполняющиеся с уровнем приви­легий 0 (обычно имеют расширение .386 для Windows 3.хх и .VXD для Windows 95), и непривилегированные драйверы, исполняющиеся, как и обычные программы, с уровнем привилегий 3 (как правило, они имеют расширение .DRV). Windows NT использует несовместимую модель драйверов, так называемую kernel-mode (режим ядра). На основе модели kernel-mode с добавлением поддержки техноло­гии PNP и понятия потоков данных в 1996 году была создана модель WDM (win32 driver model), которая теперь используется в Windows 98/NT и, по-види­мому, будет играть главную роль в дальнейшем.

Как и следовало ожидать, основным средством создания драйверов является ассемблер, и хотя использование С здесь возможно (в отличие от драйверов DOS), но сделать это сложнее: функции, к которым обращается драйвер, могут передавать параметры в регистрах; сегменты, из которых состоит драйвер, долж­ны называться определенным образом и т. д. При создании драйверов часто пользуются одновременно С и ассемблером или С и специальным пакетом, кото­рый включает в себя все необходимые для инициализации средства.

Чтобы самостоятельно создавать драйверы для любой версии Windows, необ­ходим комплект программ, документации, включаемых файлов и библиотек, рас­пространяемый Microsoft, который называется DDK - Drivers Development Kit. (DDK для Windows NT/98 распространяются бесплатно.)

Чтобы создать драйвер, лучше всего начать с одного из прилагающихся примеров и изменять/добавлять проце­дуры инициализации, обработчики сообщений, прерываний и исключении, обра­ботчики для API, предоставляемого драйвером, и т. д. Рассмотрим, как выглядит исходный текст драйвера, потому что он несколько отличается от привычных ассемблерных программ.

Любой драйвер начинается с директивы include vmm.inc, которая включает файл, содержащий определения используемых сегментов и макроопределений.

Макроопределения вида VXD_LOCKED_CODE_SEG/VXD_ LOCKED_CODE_ ENDS соответствуют директивам начала и конца сегментов (в данном случае сег­мента _LTEXT). Другие важные макроопределения - Declare_Virtual_Device и VMMCall/WDMCall. Первое - просто определение, получающее в качестве па­раметров идентификатор драйвера, название, версию, порядок загрузки и адреса основных процедур драйвера, из которых строится его заголовок. Второе - замена команды call, получающая в качестве параметра имя функции VMM или WDM, к которой надо обратиться.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]