Драйвер виртуального диска

Создание загрузочного файла 

драйвера устройства





	В листинге 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 командную строку :



                DEVICE=RDISK.SYS



	При первой  же перезагрузке драйвер будет установлен как драйвер следующего по порядку дисковода. Ничего более для установки драйвера RDISK не требуется.

            Доступ к RAM-диску возможен с помощью любых функций MS-DOS или программ,  за исключением команд DISKCOPY  и  DISKCOMP.  Обе  эти программы  ожидают  определенные  типы  дисков  и  не  работают с RAM-дисками.











Листинг 2. 

Исходный текст драйвера RAM-диска







     PAGE 60,132

; *** RDISK.ASM : MS-DOS ДРАЙВЕР RAM-ДИСКА ***

     ;

     ; Этот файл содержит исходный текст простого MS-DOS драйвера RAM-диска

     ; эмулирующего 360K флоппи-диск.

     ;

     ; В этом примере демонстрируются основные принципы построения драйвера

     ; устройств, включая один из методов, который можно использовать для

     ; отладки драйверов. Для установки этого драйвера включите в файл

     ; CONFIG.SYS строку "DEVICE=RDISK.SYS"

     ;

     ; ======== ВСПОМОГАТЕЛЬНЫЕ ФАЙЛЫ ДЛЯ ДРАЙВЕРА =====

     ;

     INCLUDE driver.inc                     ; Константы для MS-DOS драйвера

     IFDEF   DEBUG

     INCLUDE biosio.inc                     ; Определения для отладки

     ENDIF

     ;

     ; ============ КОНСТАНТЫ ========================

     ;

     ; Ограничения,накладываемые версией MS-DOS на максимальный код команды

     ;

     CMD_PRE_30               EQU      00Ch  ;  до MS-DOS версии 3.00

     CMD_PRE_32               EQU      00Fh  ;  до MS-DOS версии 3.20

     CMD_32                   EQU      018h  ;  начиная с версии 3.20

     ;

     IFDEF           DEBUG

     CR                       EQU      0Ah   ; используются в отладочных

     LF                       EQU      0Dh   ;   сообщениях

     ENDIF

     ;

     PAGE

     ;

     ; ============ ШАБЛОНЫ СТРУКТУР ==============

     ;

     request         EQU      es:[di]        ; указатель на блок запроса

     ;

     ; Структура заголовка запроса

     ;

     reqhdr          STRUC

                     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   CS:_TEXT, DS:_TEXT, ES:NOTHING

                     ORG      0

     ORIGIN          EQU      $

     ;

     ; ============= ЗАГОЛОВОК ДРАЙВЕРА ==============

     ;

                     dw       -1,-1          ; указатель на след. драйвер

                     dw       AT_IOCTL OR AT_OCRM OR AT_NET

                     dw       offset STRATEGRY       ; смещение СТРАТЕГИЙ

                     dw       offset ПРЕРЫВАНИЙ       ; смещение ПРЕРЫВАНИЙ

                     db       1,'CDEVICE'            ; кол-во устройств/имя

     ;

     ; ======= ТАБЛИЦА АДРЕСОВ ОБРАБОТЧИКОВ КОМАНД ======

     ;

     JUMPTAB        LABEL   WORD

                    dw      offset INIT             ; 0 - инициализация

                    dw      offset MEDIA_CHECK      ; 1 - проверка носителя

                    dw      offset BUILD_BPB        ; 2 - построить BPB

                    dw      offset IOCTL_INPUT      ; 3 - IOCTL ввод

                    dw      offset READ             ; 4 - ввод из устр-ва

                    dw      offset READ_NOWAIT      ; 5 - неразруш. ввод

                    dw      offset INPUT_STATUS     ; 6 - ввод статуса

                    dw      offset INPUT_FLUSH      ; 7 - сбросить ввод

                    dw      offset WRITE            ; 8 - вывод на устр-во

                    dw      offset WRITE_VERIFY     ; 9 - вывод с проверкой

                    dw      offset OUTPUT_STATUS    ; A - вывод статуса

                    dw      offset OUTPUT_FLUSH     ; B - сбросить вывод

                    dw      offset IOCTL_OUTPUT     ; C - вывод IOCTL

                    dw      offset DEVICE_OPEN      ; D - открыть устр-во

                    dw      offset DEVICE_CLOSE     ; E - закрыть устр-во

                    dw      offset REMOVABLE        ; F - носитель сменный?

                    dw      offset NO_COMMAND       ; 10

                    dw      offset NO_COMMAND       ; 11

                    dw      offset NO_COMMAND       ; 12

                    dw      offset GENERIC_IOCTL    ; 13 - Generic IOCTL

                    dw      offset NO_COMMAND       ; 14

                    dw      offset NO_COMMAND       ; 15

                    dw      offset NO_COMMAND       ; 16

                    dw      offset GET_LOGICAL      ; 17 - получить/устано-

                    dw      offset SET_LOGICAL      ; 18 - вить лог.устр-во

     ;

     ; ============ ОБЛАСТЬ ДАННЫХ ДРАЙВЕРА ==============

     ;

     reg_ptr        dd       ?               ; адрес блока запроса

     max_cmd        db       CMD_PRE_30      ; максимально допустимый код

     ;                                       ;   команды

     save_ss        dw       ?               ; значение SS на входе

     save_sp        dw       ?               ; значение SP на входе

     ;

     PAGE

     ;

     ; ============ ПРОГРАММА СТРАТЕГИЙ =============

     ;

     STRATEGY                PROC    FAR

                    mov     cs:word ptr [reg_ptr],bx

                    mov     cs:word ptr [reg_ptr+2],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 save_ss,ss      ; сохраним входное

                    mov     word ptr save_sp,sp      ; значение SS и SP

     ;

                    mov     bx,cs                    ; установим локальный

                    mov     ax,offset local_stack - 2        ; стек

                    mov     ss,bx

                    mov     sp,ax

     ;

                    les     di,[req_ptr]             ; получить адрес блока

                    mov     bl,request.command       ; запроса и команду

     ;

     ; установим заранее код ошибки на случай если команда неверная

     ;

                    mov     ax,(ST_ERROR OR UNKNOWN_COMMAND)

                    cmp     bl,[max_cmd]     ; команда поддерживается ?

                    ja      exit             ; нет - отвергаем ее

     ;

     ; Выдаем указанную команду на выполнение соответствующему обработчику.

     ; Каждый обработчик получает управление с CS и DS установленными на

     ; сегмент драйвера и ES:DI указывающем на блок запроса. Свой статус

     ; обработчики возвращают в регистре AX.

     ;

                    xor     bh,bh            ; BX - индекс в таблице

                    shl     bx,1             ;   команд

     IFDEF          DEBUG

                    call    print_command    ; выдаем имя обрабатываемой

     ENDIF                                   ;   команды

                    call    word ptr jumptab[bx]     ; вызываем обработчик

     ;

     ; Перешлем статус из регистра AX в слово состояния блока запроса

     ;

     exit:          push    cs               ; установка локального

                    pop     ds               ;   сегмента данных

     ;

                    les     di,[req_ptr]     ; получим адрес блока запроса

                    or      ax,ST_DONE       ; установим бит DONE

                    mov     request.status,ax        ; сохраним статус

     ;

                    mov     ss,word ptr save_ss      ; восстановим значение

                    mov     sp,word ptr save_sp      ;   регистров SS:SP

     ;

                    pop     es               ; восстановим содержимое

                    pop     ds               ;   регистров

                    pop     di

                    pop     si

                    pop     bp

                    pop     bx

                    pop     dx

                    pop     cx

                    pop     ax

                    ret

     interrupt      ENDP

     ;

     PAGE

     ;

     ; ============ ОБРАБОТЧИКИ КОМАНД ==============

     ;

     NO_COMAND      PROC    NEAR     ; неподдерживаемая команда

            ret                      ; возврат с ошибкой

     NO_COMMAND     ENDP

     ;

     MEDIA_CHECK    PROC    NEAR     ; 1 - проверка носителя

            mov     request.change,NotChanged

            xor     ax,ax

            ret

     MEDIA_CHECK    ENDP

     ;

     BUILD_BPB      PROC    NEAR     ; 2 - построить BPB

            mov     request.bpbptro,offset bpb

            mov     request.bpbptrs,cs

            xor     ax,ax

            ret

     BUILD_BPB      ENDP

     ;

     IOCTL_INPUT    PROC    NEAR     ; 3 - ввод IOCTL

            xor     ax,ax

            ret

     IOCTL_INPUT    ENDP

     ;

     READ           PROC    NEAR     ; 4 - ввод из устройства

            call    verify           ; проверка и установка параметров

            jc      rd_err           ; выход по ошибке

            les     di,request.bufptr   ; считываем в буфер

            rep     movsw            ; передача

            xor     ax,ax            ; нет ошибок

     rd_err:

            ret

     READ           ENDP

     ;

     READ_NOWAIT    PROC    NEAR     ; 5 - неразрушающий ввод

            xor     ax,ax            ;     без ожидания

            ret

     READ_NOWAIT    ENDP

     ;

     INPUT_STATUS   PROC    NEAR     ; 6 - ввод статуса

            xor     ax,ax

            ret

     INPUT_STATUS   ENDP

     ;

     INPUT_FLUSH    PROC    NEAR     ; 7 - сбросить входную очередь

            xor     ax,ax

            ret

     INPUT_FLUSH    ENDP

     ;

     WRITE          PROC    NEAR     ; 8 - вывод на устройство

            call    verify           ; проверка и установка параметров

            jc      wr_err           ; выход при ошибке

            push    ds               ; сохраним сегмент "сектора"

            lds     si,request.bufptr   ; записываем из буфера

            pop     es               ; на диск

            xor     di,di            ; с нулевым смещением

            rep     movsw            ; передача

            xor     ax,ax            ; нет ошибок

     wr_err:

            ret

     WRITE          ENDP

     ;

     WRITE_VERIFY   PROC    NEAR     ; 9 - вывод с проверкой

            call    write

            ret

     WRITE_VERIFY   ENDP

     ;

     OUTPUT_STATUS  PROC    NEAR     ; A - вывод статуса

            xor     ax,ax

            ret

     OUTPUT_STATUS  ENDP

     ;

     OUTPUT_FLUSH   PROC    NEAR     ; B - сбросить выходную очередь

            xor     ax,ax

            ret

     OUTPUT_FLUSH   ENDP

     ;

     IOCTL_OUTPUT   PROC    NEAR     ; C - вывод IOCTL

            xor     ax,ax

            ret

     IOCTL_OUTPUT

     ;

     DEVICE_OPEN    PROC    NEAR     ; D - открыть устройство

            xor     ax,ax

            ret

     DEVICE_OPEN    ENDP

     ;

     DEVICE_CLOSE   PROC    NEAR     ; E - закрыть устройство

            xor     ax,ax

            ret

     DEVICE_CLOSE   ENDP

     ;

     REMOVABLE      PROC    NEAR     ; F - носитель сменный ?

            mov     ax,ST_BUSY       ; нет !

            ret

     REMOVABLE      ENDP

     ;

     GENERIC_IOCTL  PROC    NEAR     ; 13 - групповой IOCTL запрос

            xor     ax,ax

            ret

     GENERIC_IOCTL  ENDP

     ;

     GET_LOGICAL    PROC    NEAR     ; 17 - получить имя логического

            xor     ax,ax            ;      диска

            ret

     GET_LOGICAL    ENDP

     ;

     SET_LOGICAL    PROC    NEAR     ; 18 - установить имя логического

            xor     ax,ax            ;      диска

            ret

     SET_LOGICAL    ENDP

     ;

     PAGE

     ; ------------ Подпрограммы обработки запросов -----------------------

     ; Эти подпрограммы вызываются для обработки параметров любого запроса

     ; на ввод/вывод.

     ; На входе :

     ;    ES:DI - содержит адрес блока запроса

     ; Действия :

     ;    Проверка параметра "номер сектора" на допустимость.

     ;    Преобразование этого параметра в "сегмент:смещение".

     ;    Выровнять счетчик для предотвращения "перекрытия".

     ; На выходе :

     ;    DS:SI - содержит адрес "сектора" в RAM-диске

     ;    ES:DI - содержит адрес блока запроса

     ;    CX - содержит количество передаваемых слов.

     ;

     verify PROC    NEAR

     ; проверим что номера начального и конечного секторов лежат в пределах

     ; от 0 до N.

            mov     cx,request.start         ; сравним номер начального

            cmp     cx,bpb.nls               ;   сектора с количеством

            jae     out_of_range             ;   логических секторов

            add     cx,request.count         ; найдем номер конечного

            dec     cx                       ;   сектора и тоже сравним

            cmp     cx,bpb.nls               ; если номера секторов

            jb      in_range                 ;   нормальные то продолжим

     ; заданные секторы не содержатся на диске

     out_of_range:

            mov     ax,ST_ERROR OR SECTOR_NOT_FOUND

            mov     request.count,0          ; ничего не было передано

            stc                              ; возвращаемся с ошибкой

            ret

     ; вычислим сегментный адрес начального сектора

     in_range:

            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     out_of_range

     ; выровняем счетчик в AX для предотвращения перекрытия

            mov     cx,word ptr request.bufptr

            cmp     ax,0                     ; смещение = 0

            je      set_size

            neg     cx                       ; остаток = 64K - смещение

            cmp     cx,ax                    ;   буфера

            jae     set_size                 ; если остаток меньше счетчика,

            mov     ax,cx                    ;   то передаем только остаток

     ; установим количество передаваемых секторов и счетчик передачи

     set_size:

            mov     cx,ax                    ; счетчик передачи в байтах

            shr     cx,1                     ; преобразуем в счетчик слов

            div     bpb.bps                  ; (DX был 0) кол-во секторов

            mov     request.count,ax         ; сохраним счетчик передачи

     ; загрузим в DS:SI адрес блока в памяти

            mov     ds,si

            xor     si,si

     ; установим направление передачи и вернемся без ошибок

            cld

            clc

            ret

     verify ENDP

     ;

     IFDEF  DEBUG

     INCLUDE        biosio.asm

     PAGE

     ;

     ; ************ КОД И ДАННЫЕ ДЛЯ ОТЛАДКИ *************

     ;

     ; Отладочные сообщения

     ;

     NO_COMMAND_msg    db   'NO COMMAND',CR,LF,'$'

     INIT_msg          db   'INITialization',CR,LF,'$'

     MEDIA_CHECK_msg   db   'MEDIA Check',CR,LF,'$'

     BUILD_BPB_msg     db   'Build BIOS Parameter Block',CR,LF,'$'

     IOCTL_INPUT_msg   db   'IO Control Input',CR,LF,'$'

     READ_msg          db   'Input from Device',CR,LF,'$'

     READ_NOWAIT_msg   db   'Nondestructive Input no-wait',CR,LF,'$'

     INPUT_STATUS_msg  db   'Input Status',CR,LF,'$'

     INPUT_FLUSH_msg   db   'Flush Input Queue',CR,LF,'$'

     WRITE_msg         db   'Output to Device',CR,LF,'$'

     WRITE_VERIFY_msg  db   'Output with Verify',CR,LF,'$'

     OUTPUT_STATUS_msg db   'Output Status',CR,LF,'$'

     OUTPUT_FLUSH_msg  db   'Flush Output Queue',CR,LF,'$'

     IOCTL_OUTPUT_msg  db   'IO Control Output',CR,LF,'$'

     DEVICE_OPEN_msg   db   'Open a Device',CR,LF,'$'

     DEVICE_CLOSE_msg  db   'Close a Device',CR,LF,'$'

     REMOVABLE_msg     db   'Is Media Removable',CR,LF,'$'

     GENERIC_IOCTL_msg db   'Generic IOCTL Request',CR,LF,'$'

     GET_LOGICAL_msg   db   'Get Logical Device',CR,LF,'$'

     SET_LOGICAL_msg   db   'Set Logical Device',CR,LF,'$'

     ;

     PAGE

     ;

     ; ===== ТАБЛИЦА АДРЕСОВ ОТЛАДОЧНЫХ СООБЩЕНИЙ =====

     ;

     message_table  LABEL   WORD

            dw      offset INIT_msg          ; 01 - инициализация

            dw      offset MEDIA_CHECK_msg   ; 02 - проверка носителя

            dw      offset BUILD_BPB_msg     ; 03 - построить BPB

            dw      offset IOCTL_INPUT_msg   ; 04 - ввод IOCTL

            dw      offset READ_msg          ; 05 - ввод из устройства

            dw      offset READ_NOWAIT_msg   ; 06 - неразруш. ввод без ожид.

            dw      offset INPUT_STATUS_msg  ; 07 - ввод статуса

            dw      offset INPUT_FLUSH_msg   ; 08 - сброс входной очереди

            dw      offset WRITE_msg         ; 09 - вывод на устройство

            dw      offset WRITE_VERIFY_msg  ; 10 - вывод с проверкой

            dw      offset OUTPUT_STATUS_msg ; 11 - вывод статуса

            dw      offset OUTPUT_FLUSH_msg  ; 12 - сброс выходной очереди

            dw      offset IOCTL_OUTPUT_msg  ; 13 - вывод IOCTL

            dw      offset DEVICE_OPEN_msg   ; 14 - открыть устройство

            dw      offset DEVICE_CLOSE_msg  ; 15 - закрыть устройство

            dw      offset REMOVABLE_msg     ; 16 - носитель сменный ?

            dw      offset NO_COMMAND_msg    ; 17 -

            dw      offset NO_COMMAND_msg    ; 18 -

            dw      offset NO_COMMAND_msg    ; 19 -

            dw      offset GENERIC_IOCTL_msg ; 20 - групповой IOCTL запрос

            dw      offset NO_COMMAND_msg    ; 21 -

            dw      offset NO_COMMAND_msg    ; 22 -

            dw      offset NO_COMMAND_msg    ; 23 -

            dw      offset GET_LOGICAL_msg   ; 24 - получить имя диска

            dw      offset SET_LOGICAL_msg   ; 25 - установить имя диска

     ;

     PAGE

     ; PRINT_COMMAND

     ;

     ; Эта процедура вызывает функцию BIOS для печати (_biosprt), передавая

     ; ей адрес строки, содержащей имя только что вызванной команды. При

     ; вызове этой процедуры удвоенный код команды передается в регистре BX.

     ; Все используемые регистры сохраняются.

     ;

     print_command  PROC    NEAR

            push    ax                       ; сохраним содержимое рег. AX

            mov     ax, BLUE_F OR BRIGHT OR BLACK_B  ; установим цвет

            push    ax

            mov     ax,word ptr message_table[bx]    ; адрес строки

            push    ax

            call    _biosprt                 ; вызываем процедуру BIOS

            add     sp,4                     ; очищаем стек от параметров

            pop     ax                       ; восстанавливаем AX и выходим

            ret

     print_command  ENDP

     ENDIF

     ;

     PAGE

     ;

;** ВНУТРЕННИЙ СТЕК И КОНЕЦ ОПЕРАЦИОННОЙ ЧАСТИ ДРАЙВЕРА **

     ;

            db      32 DUP ('stack   ')      ; внутренний стек глубиной

     local_stack    EQU     $                ;   256 байт

     ;

     bpb_tab        dw      offset bpb       ; указатель на BPB

     ;

     LAST_USED      EQU     $                ; адрес завершения

     ;

;*** ХАРАКТЕРИСТИКИ RAM-ДИСКА, ПРИНИМАЕМЫЕ ПО УМОЛЧАНИЮ ***

     ;

     ; Параметры для 5-1/4" двустороннего двойной плотности диска с девятью

     ; секторами на дорожке.

     ;

     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    TRACKS*SECTORS*SIDES     ; всего секторов

     PTOTAL  EQU    (DSIZE/16)*STOTAL        ; всего параграфов

     ;

     ; ******** НАЧАЛО ОБЛАСТИ ДАННЫХ RAM-ДИСКА **********

     ;

     ; RAM-диск д.б. выровнен на границу параграфа

     ;

            IF      ($-ORIGIN) mod 16

            ORG     ($-ORIGIN) + 16 - (($-ORIGIN) mod 16)

            ENDIF

     RDISK  LABEL   BYTE             ; начало RAM-диска

     RPARA  EQU     ($-ORIGIN)/16    ; размер кода в параграфах

     ;

     ; ------------ Блок параметров BIOS ----------------------------------

     ;

            jmp     short boot       ; короткий JMP (2 байта)

            nop                      ; требуется для boot_record

            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 (?)       ; остаток boot_sector

     ;

     ; ------------ Таблицы размещения файлов (FAT) -----------------------

     ;                                       ; первые два элемента FAT

     FAT_1  db      MTYPE,0FFh,0FFh          ; нулевой остаток FAT

            db      (DSIZE-3) DUP (0)

            db      ((FSECS-1) * DSIZE) DUP (0)

     FAT_2  db      MTYPE,0FFh,0FFh          ; первые два элемента FAT

            db      (DSIZE-3) DUP (0)        ; нулевой остаток FAT

            db      ((FSECS-1) * DSIZE) DUP (0)

     ;

     ; ------------ Сектора директория ------------------------------------

     ;

     DIREC  db      'RAM_DISK   '            ; имя тома (11 байт)

            db      08h                      ; VID

            db      10 DUP (?)               ; зарезервировано

            dw      0600h                    ; время 12:00:00 (полдень)

            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,(RPARA+PTOTAL)   ; последний параграф

            mov     request.units,1

            mov     request.bpbtabo,offset bpb_tab

            mov     request.bpbtabs,cs

            mov     al,$desig                ; скорректируем имя диска

            add     al,request.devnum

            mov     $desig,al

     ;

     ; вывод на экран идентификационной строки

            @DisStr $signon

     ;

     ; скорректируем значение "max_cmd" исходя из версии MS-DOS

            @GetDOSVersion                   ; получим номер версии MS-DOS

            cmp     al,3                     ; MS-DOS версии 3.00 и выше ?

            jb      init_done             ; нет - прекращаем инициализацию

            mov     [max_cmd],CMD_PRE_32     ; команды для MS-DOS 3.00

            cmp     ah,2                     ; MS-DOS версии 3.20 и выше ?

            jb      init_done             ; нет - прекращаем инициализацию

            mov     [max_cmd],CMD_32         ; команды для MS-DOS 3.20

     ;

     init_done:

            xor     ax,ax                    ; нет проблем !

            ret

     INIT   ENDP

     ;

     ; ************ КОНЕЦ ДРАЙВЕРА. КОНЕЦ ФАЙЛА ************

     ;

     _TEXT  ENDS

            END













Список используемой литературы



стр. 18 из 18