Создание загрузочного файла драйвера устройства В листинге 1 представлен диалог с системой при создании драйвера DRIVER. Этот файл ассемблируется и линкуется как обычная программа, после чего преобразуется в двоичный .SYS файл. Замечу, что отсутствие стека для драйвера является нормальным явлением, так как драйвер при работе использует собственный стек MS-DOS. В примере, приведенном в листинге 6-4, создается также выходной .
LST файл ассемблера и выходной .MAP файл редактора связей. Конечно же, .OBJ и .EXE файлы могут быть удалены после создания .SYS файла. Листинг 1. Процесс создания простого драйвера. C masm driver,driver,driver Microsoft Macro Assembler Version 4.00 Copyright Microsoft Corp 1981, 1983, 1984, 1985.
All rights reserved. 45976 Bytes symbol space free 0 Warning Errors 0 severe Errors C link driver,driver,driver Microsoft 8086 Object linker Version 3.00 Copyright Microsoft Corp 1983, 1984, 1985 Warning no stack segment C exe2bin driver driver.sys Драйвер виртуального диска
В листинге 2 приведен пример драйвера RAM-диска - драйвера виртуального диска, размещаемого в ОЗУ. Несмотря на свою простоту, драйвер работоспособен и может быть использован на любой MS-DOS системе начиная с версии 2.0 и выше. Данный драйвер RAM-диска, использует 360 Kбайт системной памяти для эмуляции стандартного пятидюймового дисковода. Но при использовании этого драйвера, система ПК должна иметь по крайней мере 512
Kбайт памяти. Если имеется меньше памяти или нужно просто иметь виртуальный диск меньших размеров, то можно изменить принимаемые по умолчанию параметры, описаные в секции драйвера Описание RAM-диска. После того, как программа была обработана ассемблером и редактором связей, надо переименовать ее в RDISK.SYS. И добавить в файл CONFIG.SYS командную строку DEVICERDISK.SYS При первой же перезагрузке драйвер будет установлен как драйвер
следующего по порядку дисковода. Ничего более для установки драйвера RDISK не требуется. Доступ к RAM-диску возможен с помощью любых функций MS-DOS или программ, за исключением команд DIISKCOMP. Обе эти программы ожидают определенные типы дисков и не работают с RAM-дисками. Листинг 2. Исходный текст драйвера RAM-диска
PAGE 60,132 RDISK.ASM MS-DOS ДРАЙВЕР RAM-ДИСКА Этот файл содержит исходный текст простого MS-DOS драйвера RAM-диска эмулирующего 360K флоппи-диск. В этом примере демонстрируются основные принципы построения драйвера устройств, включая один из методов, который можно использовать для отладки драйверов. Для установки этого драйвера включите в файл CONFIG.
SYS строку DEVICERDISK.SYS ВСПОМОГАТЕЛЬНЫЕ ФАЙЛЫ ДЛЯ ДРАЙВЕРА INCLUDE driver.inc Константы для MS-DOS драйвера IINCLUDE biosio.inc Определения для отладки ENDIF КОНСТАНТЫ Ограничения,накладываемые версией MS-DOS на максимальный код команды CMDPRE30 EQU 00Ch до
MS-DOS версии 3.00 CMDPRE32 EQU 00Fh до MS-DOS версии 3.20 CMD32 EQU 018h начиная с версии IFDEF DEBUG CR EQU 0Ah используются в отладочных LF EQU 0Dh сообщениях ENDISTRUC rlength db размер блока запроса unit db номер устройства command
db код команды status dw возвращаемый статус db 8 DUP зарезервировано reghdr ENDS Структура блока запроса для команды INIT inithdr STRUC db type reqhdr DUP units db количество устройств endadro dw смещение и сегмент endadrs dw адреса завершения bpbtabo dw смещение и сегмент bpbtabs dw таблицы BPB devnum db номер устройства inithdr ENDS Структура блока запроса для команды
MEDIA CHECK mchkhdr STRUC db type reqhdr DUP mbd db описатель носителя chande dw статус замены volume dd указатель на имя тома mchkhdr ENDS Структура блока запроса для команды BUILD BPB bpbhdr STRUC db type reqhdr DUP db описатель носителя dd указатель на FAT bpbptro dw смещение BPB bpbptrs dw сегмент BPB bpbhdr ENDS Структура блока запроса для команд чтениязаписи iohdr
STRUC db type reqhdr DUP db описатель носителя bufprt dd адрес буфера count dw кол-во байтсекторов start dw начального сектора nuvol dd адрес нов. имени тома iohdr ENDS Структура блока параметров BIOS BPB bpbstrc STRUC bps dw количество байтов в секторе spau db кол-во секторов в кластере nrs dw кол-во зарезервир. секторов nft db количество копий FAT nde dw кол-во элементов директория nls dw кол-во логических секторов md db байт описателя носителя
nfs dw размер FAT в секторах bpbstrc ENDS PAGE НАЧАЛО КОДА ДРАЙВЕРА TEXT SEGMENT BYTE PUBLIC CODE ASSUME CSTEXT, DSTEXT, ESNOTHING ORG 0 ORIGIN EQU ЗАГОЛОВОК ДРАЙВЕРА dw -1 1 указатель на след. драйвер dw ATIOCTL OR ATOCRM OR ATNET dw offset STRATEGRY смещение СТРАТЕГИЙ dw offset
ПРЕРЫВАНИЙ смещение ПРЕРЫВАНИЙ db 1,CDEVICE кол-во устройствимя ТАБЛИЦА АДРЕСОВ ОБРАБОТЧИКОВ КОМАНД JUMPTAB LABEL WORD dw offset INIT 0 - инициализация dw offset MEDIACHECK 1 - проверка носителя dw offset BUILDBPB 2 - построить BPB dw offset IOCTLINPUT 3 - IOCTL ввод dw offset READ 4 - ввод из устр-ва dw offset
READNOWAIT 5 - неразруш. ввод dw offset INPUTSTATUS 6 - ввод статуса dw offset INPUTFLUSH 7 - сбросить ввод dw offset WRITE 8 - вывод на устр-во dw offset WRITEVERIFY 9 - вывод с проверкой dw offset OUTPUTSTATUS A - вывод статуса dw offset OUTPUTFLUSH B - сбросить вывод dw offset IICEOPEN D - открыть устр-во dw offset
DEVICECLOSE E - закрыть устр-во dw offset REMOVABLE F - носитель сменный dw offset NOCOMMAND 10 dw offset NOCOMMAND 11 dw offset NOCOMMAND 12 dw offset GENERICIOCTL 13 - Generic IOCTL dw offset NOCOMMAND 14 dw offset NOCOMMAND 15 dw offset NOCOMMAND 16 dw offset GETLOGICAL 17 - получитьустано- dw offset
SETLOGICAL 18 - вить лог.устр-во ОБЛАСТЬ ДАННЫХ ДРАЙВЕРА regptr dd адрес блока запроса maxcmd db CMDPRE30 максимально допустимый код команды savess dw значение SS на входе savesp dw значение SP на входе PAGE ПРОГРАММА СТРАТЕГИЙ STRATEGY PROC FAR mov csword ptr regptr,bx mov csword ptr regptr2,es ret strategy ENDP ПРОГРАММА ПРЕРЫВАНИЙ INTERRUPT PROC FAR push ax сохранить все рабочие push cx регистры push dx
push bx push bp push si push di push ds push es push cs определим локальный сегмент pop ds данных mov word ptr savess,ss сохраним входное mov word ptr savesp,sp значение SS и SP mov bx,cs установим локальный mov ax,offset localstack - 2 стек mov ss,bx mov sp,ax les di,reqptr получить адрес блока mov bl,request.command запроса и команду установим заранее код ошибки на случай если команда неверная mov ax,
STERROR OR UNKNOWNCOMMAND cmp bl,maxcmd команда поддерживается ja exit нет - отвергаем ее Выдаем указанную команду на выполнение соответствующему обработчику. Каждый обработчик получает управление с CS и DS установленными на сегмент драйвера и ESDI указывающем на блок запроса. Свой статус обработчики возвращают в регистре AX. xor bh,bh BX - индекс в таблице shl bx,1 команд
IFDEF DEBUG call printcommand выдаем имя обрабатываемой ENDIF команды call word ptr jumptabbx вызываем обработчик Перешлем статус из регистра AX в слово состояния блока запроса exit push cs установка локального pop ds сегмента данных les di,reqptr получим адрес блока запроса or ax,STDONE установим бит DONE mov request.status,ax сохраним статус mov ss,word ptr savess восстановим значение
mov sp,word ptr savesp регистров SSSP pop es восстановим содержимое pop ds регистров pop di pop si pop bp pop bx pop dx pop cx pop ax ret interrupt ENDP PAGE ОБРАБОТЧИКИ КОМАНД NOCOMAND PROC NEAR неподдерживаемая команда ret возврат с ошибкой NOCOMMAND ENDP MEDIACHECK PROC NEAR 1 - проверка носителя mov request.change,NotChanged xor ax,ax ret MEDIACHECK ENDP BUILDBPB PROC
NEAR 2 - построить BPB mov request.bpbptro,offset bpb mov request.bpbptrs,cs xor ax,ax ret BUILDBPB ENDP IOCTLINPUT PROC NEAR 3 - ввод IOCTL xor ax,ax ret IOCTLINPUT ENDP READ PROC NEAR 4 - ввод из устройства call verify проверка и установка параметров jc rderr выход по ошибке les di,request.bufptr считываем в буфер rep movsw передача xor ax,ax нет ошибок rderr ret READ ENDP READNOWAIT PROC NEAR 5 - неразрушающий ввод xor ax,ax без ожидания ret
READNOWAIT ENDP INPUTSTATUS PROC NEAR 6 - ввод статуса xor ax,ax ret INPUTSTATUS ENDP INPUTFLUSH PROC NEAR 7 - сбросить входную очередь xor ax,ax ret INPUTFLUSH ENDP WRITE PROC NEAR 8 - вывод на устройство call verify проверка и установка параметров jc wrerr выход при ошибке push ds сохраним сегмент сектора lds si,request.bufptr записываем из буфера pop es на диск xor di,di с нулевым смещением rep movsw передача xor ax,ax нет ошибок wrerr ret
WRITE ENDP WRITEVERIFY PROC NEAR 9 - вывод с проверкой call write ret WRITEVERIFY ENDP OUTPUTSTATUS PROC NEAR A - вывод статуса xor ax,ax ret OUTPUTSTATUS ENDP OUTPUTFLUSH PROC NEAR B - сбросить выходную очередь xor ax,ax ret OUTPUTFLUSH ENDP IOCTLOUTPUT PROC NEAR C - вывод IOCTL xor ax,ax ret IOCTLOUTPUT DEVICEOPEN PROC NEAR D - открыть устройство xor ax,ax ret
DEVICEOPEN ENDP DEVICECLOSE PROC NEAR E - закрыть устройство xor ax,ax ret DEVICECLOSE ENDP REMOVABLE PROC NEAR F - носитель сменный mov ax,STBUSY нет ret REMOVABLE ENDP GENERICIOCTL PROC NEAR 13 - групповой IOCTL запрос xor ax,ax ret GENERICIOCTL ENDP GETLOGICAL PROC NEAR 17 - получить имя логического xor ax,ax диска ret
GETLOGICAL ENDP SETLOGICAL PROC NEAR 18 - установить имя логического xor ax,ax диска ret SETLOGICAL ENDP PAGE Подпрограммы обработки запросов Эти подпрограммы вызываются для обработки параметров любого запроса на вводвывод. На входе ESDI - содержит адрес блока запроса Действия Проверка параметра номер сектора на допустимость. Преобразование этого параметра в сегментсмещение.
Выровнять счетчик для предотвращения перекрытия. На выходе DSSI - содержит адрес сектора в RAM-диске ESDI - содержит адрес блока запроса CX - содержит количество передаваемых слов. verify PROC NEAR проверим что номера начального и конечного секторов лежат в пределах от 0 до N. mov cx,request.start сравним номер начального cmp cx,bpb.nls сектора с количеством jae outofrange
логических секторов add cx,request.count найдем номер конечного dec cx сектора и тоже сравним cmp cx,bpb.nls если номера секторов jb inrange нормальные то продолжим заданные секторы не содержатся на диске outofrange mov ax,STERROR OR SECTORNOTFOUND mov request.count,0 ничего не было передано stc возвращаемся с ошибкой ret вычислим сегментный адрес начального сектора inrange mov ax,bpb.bps количество байт в секторе mov cl,4 разделим на 16 для получения shr ax,cl размера в параграфах mul request.start смещение
параграфа относи- тельно начала диска add ax,RPARA смещение параграфа относи- mov dx,cs тельно CS add ax,dx абсолютное смещ. параграфа mov si,ax сохраним сегмент в SI вычислим и проверим счетчик передаваемых данных mov ax,bpb.bps размер сектора в байтах mul request.count счетчик передачи в байтах cmp dx,0 проверим на корректность jne outofrange выровняем счетчик в AX для предотвращения перекрытия mov cx,word ptr request.bufptr cmp ax,0 смещение 0 je setsize neg cx
остаток 64K - смещение cmp cx,ax буфера jae setsize если остаток меньше счетчика, mov ax,cx то передаем только остаток установим количество передаваемых секторов и счетчик передачи setsize mov cx,ax счетчик передачи в байтах shr cx,1 преобразуем в счетчик слов div bpb.bps DX был 0 кол-во секторов mov request.count,ax сохраним счетчик передачи загрузим в DSSI адрес блока в памяти mov ds,si xor si,si установим направление передачи и вернемся без ошибок cld
clc ret verify ENDP IFDEF DEBUG INCLUDE biosio.asm PAGE КОД И ДАННЫЕ ДЛЯ ОТЛАДКИ Отладочные сообщения NOCOMMANDmsg db NO COMMAND,CR,LF, INITmsg db INITialization,CR,LF, MEDIACHECKmsg db MEDIA Check,CR,LF, BUILDBPBmsg db Build BIOS Parameter Block,CR,LF, IOCTLINPUTmsg db
IO Control Input,CR,LF, READmsg db Input from Device,CR,LF, READNOWAITmsg db Nondestructive Input no-wait,CR,LF, INPUTSTATUSmsg db Input Status,CR,LF, INPUTFLUSHmsg db Flush Input Queue,CR,LF, WRITEmsg db Output to Device,CR,LF, WRITEVERIFYmsg db Output with Verify,CR,LF,
OUTPUTSTATUSmsg db Output Status,CR,LF, OUTPUTFLUSHmsg db Flush Output Queue,CR,LF, IOCTLOUTPUTmsg db IO Control Output,CR,LF, DEVICEOPENmsg db Open a Device,CR,LF, DEVICECLOSEmsg db Close a Device,CR,LF, REMOVABLEmsg db Is Media Removable,CR,LF, GENERICIOCTLmsg db Generic
IOCTL Request,CR,LF, GETLOGICALmsg db Get Logical Device,CR,LF, SETLOGICALmsg db Set Logical Device,CR,LF, PAGE ТАБЛИЦА АДРЕСОВ ОТЛАДОЧНЫХ СООБЩЕНИЙ messagetable LABEL WORD dw offset INITmsg 01 - инициализация dw offset MEDIACHECKmsg 02 - проверка носителя dw offset BUILDBPBmsg 03 - построить
BPB dw offset IOCTLINPUTmsg 04 - ввод IOCTL dw offset READmsg 05 - ввод из устройства dw offset READNOWAITmsg 06 - неразруш. ввод без ожид. dw offset INPUTSTATUSmsg 07 - ввод статуса dw offset INPUTFLUSHmsg 08 - сброс входной очереди dw offset WRITEmsg 09 - вывод на устройство dw offset WRITEVERIFYmsg 10 - вывод с проверкой dw offset OUTPUTSTATUSmsg 11 - вывод статуса dw offset OUTPUTFLUSHmsg 12 - сброс выходной очереди dw offset
IOCTLOUTPUTmsg 13 - вывод IOCTL dw offset DEVICEOPENmsg 14 - открыть устройство dw offset DEVICECLOSEmsg 15 - закрыть устройство dw offset REMOVABLEmsg 16 - носитель сменный dw offset NOCOMMANDmsg 17 - dw offset NOCOMMANDmsg 18 - dw offset NOCOMMANDmsg 19 - dw offset GENERICIOCTLmsg 20 - групповой IOCTL запрос dw offset NOCOMMANDmsg 21 - dw offset
NOCOMMANDmsg 22 - dw offset NOCOMMANDmsg 23 - dw offset GETLOGICALmsg 24 - получить имя диска dw offset SETLOGICALmsg 25 - установить имя диска PAGE PRINTCOMMAND Эта процедура вызывает функцию BIOS для печати biosprt, передавая ей адрес строки, содержащей имя только что вызванной команды. При вызове этой процедуры удвоенный код команды передается в регистре BX. Все используемые регистры сохраняются. printcommand
PROC NEAR push ax сохраним содержимое рег. AX mov ax, BLUEF OR BRIGHT OR BLACKB установим цвет push ax mov ax,word ptr messagetablebx адрес строки push ax call biosprt вызываем процедуру BIOS add sp,4 очищаем стек от параметров pop ax восстанавливаем AX и выходим ret printcommand ENDP ENDIF PAGE ВНУТРЕННИЙ СТЕК И КОНЕЦ ОПЕРАЦИОННОЙ ЧАСТИ ДРАЙВЕРА db 32 DUP stack внутренний стек глубиной localstack
EQU 256 байт bpbtab dw offset bpb указатель на BPB LASTUSED EQU адрес завершения ХАРАКТЕРИСТИКИ RAM-ДИСКА, ПРИНИМАЕМЫЕ ПО УМОЛЧАНИЮ Параметры для 5-14 двустороннего двойной плотности диска с девятью секторами на дорожке. MTYPE EQU 0FDh байт описателя носителя TRACKS EQU 40 40 дорожек SECTORS EQU 9 9 секторов на дорожке
DSIZE EQU 512 512 байт в секторе SIDES EQU 2 2 стороны на диске FSECS EQU 2 количество секторов в FAT DIREN EQU 112 количество элементов директория DSECS EQU 7 7 секторов в директории CLSIZ EQU 2 2 сектора в кластере STOTAL EQU TRACKSSECTORSSIDES всего секторов PTOTAL EQU DSIZE16STOTAL всего параграфов НАЧАЛО ОБЛАСТИ ДАННЫХ
RAM-ДИСКА RAM-диск д.б. выровнен на границу параграфа IF -ORIGIN mod 16 ORG -ORIGIN 16 - -ORIGIN mod 16 ENDIF RDISK LABEL BYTE начало RAM-диска RPARA EQU -ORIGIN16 размер кода в параграфах Блок параметров BIOS jmp short boot короткий JMP 2 байта nop требуется для bootrecord db IBM 3.1 8 байт имя и версия bpb bpbstrc DSIZE,CLSIZ,1,2,DIREN,
STOTAL,MTYPE,FSECS dw SECTORS количество секторов на дорожке dw SIDES количество головок чтениязаписи dw 0 количество скрытых секторов boot db DSIZE-30 DUP остаток bootsector Таблицы размещения файлов FAT первые два элемента FAT FAT1 db MTYPE,0FFh,0FFh нулевой остаток FAT db DSIZE-3 DUP 0 db FSECS-1 DSIZE DUP 0 FAT2 db
MTYPE,0FFh,0FFh первые два элемента FAT db DSIZE-3 DUP 0 нулевой остаток FAT db FSECS-1 DSIZE DUP 0 Сектора директория DIREC db RAMDISK имя тома 11 байт db 08h VID db 10 DUP зарезервировано dw 0600h время 120000 полдень dw 021h дата 1 января 1980 года dw 0 начальный кластер 0 dd 0 размер файла 0 db DSIZE-32 DUP 0 нулевой остаток директория db
DSECS-1 DSIZE DUP 0 BUFFER LABEL BYTE начало области данных ПРОЦЕДУРА ИНИЦИАЛИЗАЦИИ INCLUDE stdmac.inc Область данных инициализации signon db RAM DISK Driver Version 1.00 Installed Drive desig db A crlf db 0Dh,0Ah, Начало процедуры инициализации INIT PROC NEAR 00 - инициализация установим адрес завершения, количество устройств и указатель на таблицу
BPB mov request.endadro,0 адрес конца драйвера mov request.endadrs,cs add request.endadrs,RPARAPTOTAL последний параграф mov request.units,1 mov request.bpbtabo,offset bpbtab mov request.bpbtabs,cs mov al,desig скорректируем имя диска add al,request.devnum mov desig,al вывод на экран идентификационной строки DisStr signon скорректируем значение maxcmd исходя из версии MS-DOS GetDOSVersion получим номер версии MS-DOS cmp al,3
MS-DOS версии 3.00 и выше jb initdone нет - прекращаем инициализацию mov maxcmd,CMDPRE32 команды для MS-DOS 3.00 cmp ah,2 MS-DOS версии 3.20 и выше jb initdone нет - прекращаем инициализацию mov maxcmd,CMD32 команды для MS-DOS 3.20 initdone xor ax,ax нет проблем ret INIT ENDP КОНЕЦ ДРАЙВЕРА. КОНЕЦ ФАЙЛА TEXT ENDS END
! |
Как писать рефераты Практические рекомендации по написанию студенческих рефератов. |
! | План реферата Краткий список разделов, отражающий структура и порядок работы над будующим рефератом. |
! | Введение реферата Вводная часть работы, в которой отражается цель и обозначается список задач. |
! | Заключение реферата В заключении подводятся итоги, описывается была ли достигнута поставленная цель, каковы результаты. |
! | Оформление рефератов Методические рекомендации по грамотному оформлению работы по ГОСТ. |
→ | Виды рефератов Какими бывают рефераты по своему назначению и структуре. |