Створення завантажувального файлу драйвера пристрою p>
У лістингу 1 представлений діалог з системою при створенні драйвера
"DRIVER". Цей файл ассембліруется та лінки як звичайна програма, післячого перетворюється на двійковий. SYS файл. Зауважу, що відсутність стека длядрайвера є нормальним явищем, тому що драйвер при роботівикористовує власний стек MS-DOS. p>
У прикладі, наведеному в лістингу 6-4, створюється також вихідний
. LST файл асемблера і вихідний. MAP файл редактора зв'язків. Звичайно ж,
. OBJ і. EXE файли можуть бути вилучені після створення. SYS файлу. P>
Лістинг 1. P>
Процес створення простого драйвера. P>
C> masm driver, driver , driver; p>
Microsoft Macro Assembler Version 4.00 p>
Copyright Microsoft Corp 1981, 1983, 1984, 1985. p>
All rights reserved. p>
45976 Bytes symbol space free p>
0 Warning Errors p>
0 severe Errors p>
C> link driver, driver, driver; p>
Microsoft 8086 Object linker p>
Version 3.00 Copyright Microsoft Corp 1983, 1984, 1985 p>
Warning: no stack segment p>
C> exe2bin driver driver.sys p>
Драйвер віртуального диска p>
У лістингу 2 наведено приклад драйвера RAM-диска - драйверавіртуального диска, що розміщується в ОЗУ. Незважаючи на свою простоту, драйверпрацездатний і може бути використаний на будь-який MS-DOS системі починаючи зверсії 2.0 і вище. Даний драйвер RAM-диска, використовує 360 Kбайт системноїпам'яті для емуляції стандартного п'ятидюймовий дисководу. Але привикористанні цього драйвера, система ПК повинна мати принаймні 512
Kбайт пам'яті. Якщо є менше пам'яті чи потрібно просто мати віртуальнийдиск менших розмірів, то можна змінити прийняті за замовчуваннямпараметри, описані в секції драйвера "Опис RAM-диска". p>
Після того, як програма була оброблена асемблером і редакторомзв'язків, треба перейменувати її в RDISK.SYS. І додати у файл CONFIG.SYSкомандний рядок: p>
DEVICE = RDISK.SYS p>
При першому ж перезавантаження драйвер буде встановлений як драйвернаступного по порядку дисководу. Нічого більше для установки драйвера RDISKне потрібно. p>
Доступ до RAM-диску можливий за допомогою будь-яких функцій MS-DOS абопрограм, за винятком команд DISKCOPY і DISKCOMP. Обидві ці програми очікують певні типи дисків і не працюють з RAM-дисками. P>
Лістинг 2. P>
Оригінальний текст драйвера RAM-диска p>
PAGE 60,132
; *** RDISK.ASM: MS-DOS ДРАЙВЕР RAM-ДИСКУ *** p>
; p>
; Цей файл містить вихідний текст простого MS-DOS драйвера RAM-диска p >
; емулює 360K флоппі-диск. p>
; p>
; У цьому прикладі демонструються основні принципи побудови драйвера p>
; пристроїв, включаючи один з методів, який можна використовувати для p>
; налагодження драйверів. Для встановлення цього драйвера включіть у файл p>
; CONFIG.SYS рядок "DEVICE = RDISK.SYS" p>
; p>
; ======== ДОПОМІЖНІ ФАЙЛИ ДЛЯ ДРАЙВЕРА ===== p>
; p>
INCLUDE driver.inc; Константи для MS-DOS драйвера p>
IFDEF DEBUG p>
INCLUDE biosio.inc; Визначення для налагодження p>
ENDIF p>
; p>
; ============ КОНСТАНТА ==== ==================== p>
; p>
; Обмеження, що накладаються версією MS-DOS на максимальний код команди p >
; p>
CMD_PRE_30 EQU 00Ch; до MS-DOS версії 3.00 p>
CMD_PRE_32 EQU 00Fh; до MS-DOS версії 3.20 p>
CMD_32 EQU 018h; починаючи з версії 3.20 p>
; p>
IFDEF DEBUG p>
CR EQU 0Ah; використовуються в оцінних p>
LF EQU 0Dh; повідомленнях p >
ENDIF p>
; p>
PAGE p>
; p>
; ============ ШАБЛОНИ СТРУКТУР ============== p>
; request EQU es: [di]; покажчик на блок запиту p>
; p>
; Структура заголовка запиту p>
; reqhdr STRUC rlength db? ; Розмір блоку запиту unit db? ; Номер пристрою command db? ; Код команди status dw? ; Повертається статус db 8 DUP (?); Зарезервовано reghdr ENDS p>
; p>
; Структура блоку запиту для команди INIT p>
; inithdr STRUC db (type reqhdr) DUP (?) units db? ; Кількість пристроїв endadro dw? ; Зміщення і сегмент endadrs dw? ; Адреси завершення bpbtabo dw? ; Зміщення і сегмент bpbtabs dw? ; Таблиці BPB devnum db? ; Номер пристрою inithdr ENDS p>
; p>
; Структура блоку запиту для команди MEDIA CHECK p>
; mchkhdr STRUC db (type reqhdr) DUP (?) Mbd db? ; Описувач носія chande dw? ; Статус заміни volume dd? ; Вказівник на ім'я томи mchkhdr ENDS p>
; p>
; Структура блоку запиту для команди BUILD BPB p>
; bpbhdr STRUC db (type reqhdr) DUP (?) Db ? ; Описувач носія dd? ; Покажчик на FAT bpbptro dw? ; Зсув BPB bpbptrs dw? ; Сегмент BPB bpbhdr ENDS p>
; p>
; Структура блоку запиту для команд читання/запису p>
; iohdr STRUC db (type reqhdr) DUP (?) Db? ; Описувач носія bufprt dd? ; Адреса буфера count dw? ; К-ть байт/секторів start dw? ; # Початкового сектора nuvol dd? ; Адреса нов. імені томи iohdr ENDS p>
; p>
; Структура блоку параметрів BIOS (BPB) p>
; bpbstrc STRUC bps dw? ; Кількість байтів в секторі spau db? ; Кількість секторів в кластері nrs dw? ; Кількість зарезервують. секторів nft db? ; Кількість копій FAT nde dw? ; Кількість елементів директорія nls dw? ; Кількість логічних секторів md db? ; Байт описувача носія nfs dw? ; Розмір FAT у секторах bpbstrc ENDS p>
; p>
PAGE p>
; p>
; =========== == ПОЧАТОК КОДА ДРАЙВЕРА ================ p>
; p>
_TEXT SEGMENT BYTE PUBLIC 'CODE' p>
ASSUME CS: _TEXT, DS: _TEXT, ES: NOTHING p>
ORG 0 p>
ORIGIN EQU $ p>
; p>
; === ========== ЗАГОЛОВОК ДРАЙВЕРА ============== p>
; dw -1, -1; покажчик на слід. драйвер dw AT_IOCTL OR AT_OCRM OR AT_NET dw offset STRATEGRY; зсув СТРАТЕГІЯ dw offset ПЕРЕРИВАННЯ; зсув ПЕРЕРИВАННЯ db 1, 'CDEVICE'; кількість пристроїв/ім'я p>
; p>
; == ===== ТАБЛИЦЯ АДРЕСОЮ Оброблювач КОМАНД ====== p>
; p>
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 - вити лог.устр-во p>
; p>
; ============ ОБЛАСТЬ ДАНИХ ДРАЙВЕРА ========= ===== p>
; reg_ptr dd? ; Адресу блоку запиту max_cmd db CMD_PRE_30; максимально допустимий код p>
;; команди save_ss dw? ; Значення SS на вході save_sp dw? ; Значення SP на вході p>
; p>
PAGE p>
; p>
; ============ ПРОГРАМА СТРАТЕГІЯ ============= p>
; p>
STRATEGY PROC FAR mov cs: word ptr [reg_ptr], bx mov cs: word ptr [reg_ptr + 2], es ret strategy ENDP p>
; p>
; ============ ПРОГРАМА ПЕРЕРИВАННЯ ============= == p>
; p>
INTERRUPT PROC FAR push ax; зберегти всі робочі push cx; регістри push dx push bx push bp push si push di push ds push es p>
; push cs; визначимо локальний сегмент pop ds; даних p>
; mov word ptr save_ss, ss; збережемо вхідна mov word ptr save_sp, sp; значення SS і SP p>
; mov bx , cs; встановимо локальний mov ax, offset local_stack - 2; стек mov ss, bx mov sp, ax p>
; les di, [req_ptr]; отримати адресу блоку mov bl, request.command; запиту і команду p>
; p>
; встановимо заздалегідь код помилки на випадок якщо команда невірна p>
; mov ax, (ST_ERROR OR UNKNOWN_COMMAND) cmp bl, [max_cmd]; команда підтримується ? ja exit; немає - відкидаємо її p>
; p>
; Видаємо зазначену команду на виконання відповідного обробнику. p>
; Кожен оброблювач одержує управління з CS і DS встановленими на
; сегмент драйвера і ES: DI вказує на блок запиту. Свій статус p>
; обробники повертають в регістрі AX. P>
; xor bh, bh; BX - індекс в таблиці shl bx, 1; команд p>
IFDEF DEBUG call print_command; видаємо ім'я оброблюваної p>
ENDIF; команди call word ptr jumptab [bx]; викликаємо обробник p>
; p>
; перешлемо статус з регістра AX в слово стану блоку запиту p>
; exit: push cs; установка локального pop ds; сегмента даних p>
; les di, [req_ptr]; отримаємо адресу блоку запиту or ax, ST_DONE; встановимо біт DONE mov request . status, ax; збережемо статус p>
; mov ss, word ptr save_ss; відновимо значення mov sp, word ptr save_sp; регістрів SS: SP p>
; pop es; відновимо вміст pop ds ; регістрів pop di pop si pop bp pop bx pop dx pop cx pop ax ret interrupt ENDP p>
; p>
PAGE p>
; p>
; ============ Оброблювач КОМАНД ============== p>
; p>
NO_COMAND PROC NEAR; не підтримується команда ret; повернення з помилкою p>
NO_COMMAND ENDP p>
; p>
MEDIA_CHECK PROC NEAR; 1 - перевірка носія mov request.change, NotChanged xor ax, ax ret p>
MEDIA_CHECK ENDP p>
; p>
BUILD_BPB PROC NEAR; 2 - побудувати BPB mov request.bpbptro, offset bpb mov request.bpbptrs, cs xor ax, ax ret p>
BUILD_BPB ENDP p>
; p>
IOCTL_INPUT PROC NEAR; 3 - введення IOCTL xor ax, ax ret p>
IOCTL_INPUT ENDP p>
; p>
READ PROC NEAR; 4 - введення з пристрою call verify; перевірка і установка параметрів jc rd_err; вихід помилково les di, request.bufptr; зчитуємо в буфер rep movsw; передача xor ax, ax; немає помилок rd_err: ret p>
READ ENDP p>
; p>
READ_NOWAIT PROC NEAR; 5 - неруйнівний введення xor ax, ax; без очікування ret p> < p> READ_NOWAIT ENDP p>
; p>
INPUT_STATUS PROC NEAR; 6 - введення статусу xor ax, ax ret p>
INPUT_STATUS ENDP p>
;
INPUT_FLUSH PROC NEAR; 7 - скинути вхідної черги xor ax, ax ret p>
INPUT_FLUSH ENDP p>
; p>
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 p>
WRITE ENDP p>
; p>
WRITE_VERIFY PROC NEAR; 9 - виведення з перевіркою call write ret p >
WRITE_VERIFY ENDP p>
; p>
OUTPUT_STATUS PROC NEAR; A - висновок статусу xor ax, ax ret p>
OUTPUT_STATUS ENDP p>
; p>
OUTPUT_FLUSH PROC NEAR; B - скинути вихідну чергу xor ax, ax ret p>
OUTPUT_FLUSH ENDP p>
; p>
IOCTL_OUTPUT PROC NEAR; C - висновок IOCTL xor ax, ax ret p>
IOCTL_OUTPUT p>
; p>
DEVICE_OPEN PROC NEAR; D - відкрити пристрій xor ax, ax ret p> < p> DEVICE_OPEN ENDP p>
; p>
DEVICE_CLOSE PROC NEAR; E - закрити пристрій xor ax, ax ret p>
DEVICE_CLOSE ENDP p>
;
REMOVABLE PROC NEAR; F - носій змінний? mov ax, ST_BUSY, нема! ret p>
REMOVABLE ENDP p>
; p>
GENERIC_IOCTL PROC NEAR; 13 - груповий IOCTL запит xor ax, ax ret p>
GENERIC_IOCTL ENDP p>
; p>
GET_LOGICAL PROC NEAR; 17 - отримати ім'я логічного xor ax, ax; диска ret p>
GET_LOGICAL ENDP p>
; p>
SET_LOGICAL PROC NEAR; 18 - встановити ім'я логічного xor ax, ax; диска ret p>
SET_LOGICAL ENDP p>
; p>
PAGE p>
; ------------ Підпрограми обробки запитів ----------------------- p>
; Ці підпрограми викликаються для обробки параметрів будь-якого запиту p>
; на ввід/вивід. p>
; На вході: p>
; ES: DI - містить адресу блоку запиту p>
; Дії: p>
; Перевірка параметра "номер сектора" на допустимість. p>
; Перетворення цього параметра в "сегмент: зсув". p>
; Вирівняти лічильник для запобігання "перекриття". p>
; На виході: p>
; DS: SI - містить адресу "сектору" в RAM-диску p>
; ES: DI - містить адресу блоку запиту p>
; CX - містить кількість переданих слів. p>
; verify PROC NEAR p>
; перевіримо що номери початкового і кінцевого секторів лежать в межах
; від 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; нормальні то продовжимо p>
; задані сектори не містяться на диску out_of_range: mov ax, ST_ERROR OR SECTOR_NOT_FOUND mov request.count, 0; нічого не було передано stc; повертаємося з помилкою ret p >
; обчислимо сегментний адреса початкового сектора in_range: mov ax, bpb.bps; кількість байт в секторі mov cl, 4; розділимо на 16 для отримання shr ax, cl; розміру в параграфах mul request.start; зсув параграфа відноси - p>
; тельно початку диска add ax, RPARA; зсув параграфа відноси-mov dx, cs; тельно CS add ax, dx; абсолютна зміщені. параграфа mov si, ax; збережемо сегмент у SI p>
; обчислимо і перевіримо лічильник переданих даних mov ax, bpb.bps; розмір сектора в байтах mul request.count; лічильник передачі в байтах cmp dx, 0; перевіримо на коректність jne out_of_range p>
; вирівняємо лічильник у 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; то передаємо тільки залишок p>
; встановимо кількість переданих секторів і лічильник передачі set_size: mov cx, ax; лічильник передачі в байтах shr cx, 1; перетворимо в лічильник слів div bpb.bps ; (DX був 0) кількість секторів mov request.count, ax; збережемо лічильник передачі p>
; завантажимо в DS: SI адресу блоку в пам'яті mov ds, si xor si, si p> < p>; встановимо напрям передачі і повернемося без помилок cld clc ret verify ENDP p>
; p>
IFDEF DEBUG p>
INCLUDE biosio.asm p>
PAGE p>
; p>
; ************ КОД І ДАНІ для налагодження ************* p >
; p>
; налагодження повідомлення p>
; p>
NO_COMMAND_msg db 'NO COMMAND', CR, LF ,'$' p>
INIT_msg db 'INITialization', CR, LF ,'$' p>
MEDIA_CHECK_msg db 'MEDIA Check', CR, LF ,'$' p>
BUILD_BPB_msg db 'Build BIOS Parameter Block' , CR, LF ,'$' p>
IOCTL_INPUT_msg db 'IO Control Input', CR, LF ,'$' p>
READ_msg db 'Input from Device', CR, LF, ' $ ' p>
READ_NOWAIT_msg db' Nondestructive Input no-wait ', CR, LF ,'$' p>
INPUT_STATUS_msg db' Input Status ', CR, LF ,'$' p >
INPUT_FLUSH_msg db 'Flush Input Queue', CR, LF ,'$' p>
WRITE_msg db 'Output to Device', CR, LF ,'$' p>
WRITE_VERIFY_msg db 'Output with Verify', CR, LF ,'$' p>
OUTPUT_STATUS_msg db 'Output Status', CR, LF ,'$' p>
OUTPUT_FLUSH_msg db 'Flush Output Queue', CR , LF ,'$' p>
IOCTL_OUTPUT_msg db 'IO Control Output', CR, LF ,'$' p>
DEVICE_OPEN_msg db 'Open a Device', CR, LF, '$' p>
DEVICE_CLOSE_msg db 'Close a Device', CR, LF ,'$' p>
REMOVABLE_msg db 'Is Media Removable', CR, LF ,'$' p>
GENERIC_IOCTL_msg db 'Generic IOCTL Request', CR, LF ,'$' p>
GET_LOGICAL_msg db 'Get Logical Device', CR, LF ,'$' p>
SET_LOGICAL_msg db 'Set Logical Device ', CR, LF ,'$' p>
; p>
PAGE p>
; p>
; ===== ТАБЛИЦЯ АДРЕСОЮ Відлагоджувальна ПОВІДОМЛЕНЬ ===== p>
; 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 - встановити ім'я диска p>
; p>
PAGE p>
; PRINT_COMMAND p>
; p>
; Ця процедура викликає функцію BIOS для друку (_biosprt), передаючи p>
; їй адресу рядка, що містить ім'я тільки що викликаної команди. При p>
; виклику цієї процедури подвоєний код команди передається в регістрі
BX. P>
; Усі використовувані регістри зберігаються. P>
; 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 p>
ENDIF p>
; p>
PAGE p>
;
; ** ВНУТРІШНІЙ СТЕК І КІНЕЦЬ ОПЕРАЦІЙНОЇ ЧАСТИНИ ДРАЙВЕРА ** p>
; db 32 DUP ( 'stack'); внутрішній стек глибиною local_stack EQU $; 256 байт p>
; bpb_tab dw offset bpb ; покажчик на BPB p>
; p>
LAST_USED EQU $; адреса завершення p>
;
; *** ХАРАКТЕРИСТИКИ RAM-ДИСКУ, приймається за замовчуванням *** p>
; p>
; Параметри для 5-1/4 "двосторонньої подвійної щільності диска з дев'ятьма p> < p>; секторами на доріжці. p>
; p>
MTYPE EQU 0FDh; байт описувача носія p>
TRACKS EQU 40; 40 доріжок p>
SECTORS EQU 9; 9 секторів на доріжці p>
DSIZE EQU 512; 512 байт в секторі p>
SIDES EQU 2; 2 сторони на диску p>
; p> < p> FSECS EQU 2; кількість секторів в FAT p>
DIREN EQU 112; кількість елементів директорія p>
DSECS EQU 7; 7 секторів в директорії p>
CLSIZ EQU 2; 2 сектора в кластері p>
; p>
STOTAL EQU TRACKS * SECTORS * SIDES; всього секторів p>
PTOTAL EQU (DSIZE/16) * STOTAL; всього параграфів p>
; p>
; ******** ПОЧАТОК ОБЛАСТІ ДАНИХ RAM-ДИСКУ ********** p>
; p>
; RAM-диск д.б.н. вирівняний на кордон параграфа p>
; p>
IF ($-ORIGIN) mod 16 p>
ORG ($-ORIGIN ) + 16 - (($-ORIGIN) mod 16) p>
ENDIF p>
RDISK LABEL BYTE; початок RAM-диска p>
RPARA EQU ($-ORIGIN)/16; розмір коду в параграфах p>
; p>
; ------------ Блок параметрів BIOS ------------ ---------------------- p>
; jmp short boot; короткий JMP (2 байти) nop; потрібно для boot_record db 'IBM 3.1' ; 8 байт ім'я і версія p>
; bpb bpbstrc dw SECTORS; кількість секторів на доріжці dw SIDES; кількість головок читання/запису dw 0; кількість прихованих секторів boot: db (DSIZE-30) DUP (?); залишок boot_sector p>
; p>
; ------------ Таблиці розміщення файлів (FAT) -------------- --------- p>
;; перший два елементи FAT p>
FAT_1 db MTYPE, 0FFh, 0FFh; нульовий залишок FAT db (DSIZE-3) DUP (0) db ((FSECS-1) * DSIZE) DUP (0) p>
FAT_2 db MTYPE, 0FFh, 0FFh; перші два елементи FAT db (DSIZE-3) DUP (0); нульовий залишок FAT db (( FSECS-1) * DSIZE) DUP (0) p>
; p>
; ------------ Сектора директорія --------- --------------------------- p>
; p>
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) p>
BUFFER LABEL BYTE; початок області даних p>
; p>
; ************ процедури ініціалізації ************** p>
; p>
INCLUDE stdmac.inc p>
; p>
; ============ Область даних ініціалізації =========== p> < p>; p>
$ signon db 'RAM DISK Driver Version 1.00 Installed: Drive p>
$ desig db' A ' p>
$ crlf db 0Dh, 0Ah,' $ ' p>
; p>
; ============ Початок процедури ініціалізації =========== p>
; p>
INIT PROC NEAR; 00 - ініціалізація p>
; p>
; встановимо адреса завершення, кількість пристроїв і покажчик на p>
; таблицю BPB p>
; 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 p>
; p>
; висновок на екран ідентифікаційної рядка p>
@ DisStr $ signon p>
; p>
; скорегуємо значення "max_cmd" виходячи з версії MS-DOS p>
@ 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 p>
; init_done: xor ax, ax; немає проблем! ret p>
INIT ENDP p>
; p>
; ************ КІНЕЦЬ ДРАЙВЕРА. КІНЕЦЬ файла ************ p>
;
_TEXT ENDS p>
END p>
Список використаної літератури p>
p>