Завершаю цикл статей по структурам MS DOS. В этой теме расскажу про список загружаемых драйверов устройств.
Все загруженные драйверы (резидентные или подключенные к ОС во время обработки файла config.sys) связаны в список. Сразу после векторной таблицы связи (CVT - viewtopic.php?t=97) записан заголовок NUL-драйвера, он первый в списке драйверов и служит исключительно для обозначения начала списка. Возможно в дальнейшем подробнее расскажу про драйверы, но в данной статье мы разберём лишь структуру списка.
Драйвер - программа, которая имеет размер не более 64 кБ и начинается с заголовка. Вот структура заголовка драйвера устройства:
(0) dd next указатель на заголовок следующего драйвера. Если смещение адреса следующего драйвера равно FFFF, это последний драйвер в цепочке
(+4)dw attrib атрибуты драйвера
(+6)dw strateg смещение программы стратегии драйвера
(+8)dw interrupt смещение программы обработки прерывания для драйвера
(+10)8 dev_name имя устройства для символьных устройств или количество обслуживаемых устройств для блочных устройств.
Напишу программу, которая сканирует список драйверов и отправляет результат на стандартное устройство вывод:
Код: Выделить всё
.model tiny
.286
code segment
org 100h
start:
mov ah, 52h
int 21h
;Read adress of driver
mov ax, word ptr es:[bx+34]
mov dx, word ptr es:[bx+36]
mov drv_addr, ax
mov drv_addr+2, dx
read_driver_struc:
push word ptr drv_addr
push offset display.num0+8
call hex_ascii
push word ptr drv_addr+2
push offset display.num0+3
call hex_ascii
push word ptr drv_addr
push word ptr drv_addr+2
pop ds
pop si ;DS:SI - address of driver
;Read driver header. DS:SI - reading driver
push ss
pop es
mov di, offset drv.next
mov cl, 9d
rep movsw
push es
pop ds
;Read next driver address
push drv.next
push offset display.num1+8
call hex_ascii
push drv.next+2
push offset display.num1+3
call hex_ascii
;Read attribute of driver
push drv.attrib
push offset display.num2+3
call hex_ascii
;Read strategy of driver
push drv.strateg
push offset display.num3+3
call hex_ascii
;Read offset of interrupt driver
push drv.interrupt
push offset display.num4+3
call hex_ascii
;Display part of header of driver
mov ah, 9d
mov dx, offset display.drv_adr
int 21h
;Block or symbol device?
test drv.attrib, 8000h
jz block
;Read name of driver for symbol device
mov si, offset drv.dev_name
mov di, offset display.num5
mov cx, 4d
rep movsw
mov ah, 9d
mov dx, offset display.dev_name_
int 21h
jmp next_driver
;Read count of devices serviced by driver for block device
block:
xor ax, ax
mov al, drv.dev_name
push ax
push offset display.num6+2
call hex_dec
mov ah, 9d
mov dx, offset display.block_num
int 21h
;Write address of next driver of jmp exit
next_driver:
cmp drv.next, 0FFFFh
jz exit
mov ax, drv.next
mov bx, drv.next+2
mov drv_addr, ax
mov drv_addr, bx
mov si, offset display.num6
mov cx, 3d
clr_num6:
mov byte ptr[si], 0
inc si
loop clr_num6
jmp read_driver_struc
exit:
mov ax, 4c00h
int 21h
drv_addr dw 2d dup(0)
display_ struc
drv_adr db 'DRIVER ADDRESS:', 9d
num0 db 4d dup(0), ':', 4d dup(0), 0Ah, 0Dh
next_ db 'NEXT DRIVER: ', 9d
num1 db 4d dup(0), ':', 4d dup(0), 0Ah, 0Dh
attrib_ db 'ATTRIBUTE: ', 9d
num2 db 4d dup(0), 0Ah, 0Dh
strateg_ db 'STRATEGY: ', 9d
num3 db 4d dup(0), 0Ah, 0Dh
interrupt_ db 'INT OF DRIVER: ', 9d
num4 db 4d dup(0), 0Ah, 0Dh, 24h
dev_name_ db 'NAME: ', 9d
num5 db 8d dup(0), 0Ah, 0Dh
str_ db '---------------', 0Ah, 0Dh, 24h
block_num db 'NUM OF DEVICES:', 9d
num6 db 3d dup(0), 0Ah, 0Dh
str2_ db '---------------', 0Ah ,0Dh, 24h
display_ ends
display display_ <>
drv_ struc
next dw 2d dup(0)
attrib dw ?
strateg dw ?
interrupt dw ?
dev_name db 8d dup(0)
drv_ ends
drv drv_ <>
;------------------------------------------
;HEX IN DECIMAL ASCII PROCEDURE.
;PARAMETERS(STACK):
;- NUMBER
;- LAST BYTE IN MEMORY FOR DISPLAY
hex_dec proc uses ax bx di dx bp
mov bp, sp
mov ax, word ptr ss:[bp+14]
mov di, word ptr ss:[bp+12]
mov bx, 0Ah
xor dx, dx
in_decimal:
cmp ax, 0
jz stop_decimal
div bx
add dl, 30h
mov byte ptr[di], dl
xor dx, dx
dec di
jmp in_decimal
stop_decimal:
ret 4
hex_dec endp
;---------------------------------------
;HEX NUMBER IN ASCII CODE PROCEDURE.
;PARAMETERS(STACK):
;- NUMBER
;- LAST BYTE IN ARRAY FOR DISPLAY
hex_ascii proc uses ax bx di cx bp
mov bp, sp
mov bx, word ptr ss:[bp+14]
mov di, word ptr ss:[bp+12]
mov cx, 4d
translate:
mov ax, bx
and ax, 0Fh
cmp al, 9d
ja letter
add al, 30h
mov byte ptr[di], al
ror bx, 4d
dec di
loop translate
jmp end_of_trans
letter:
add al, 37h
mov byte ptr[di], al
ror bx, 4d
dec di
loop translate
end_of_trans:
ret 4
hex_ascii endp
code ends
end start
Была использована версия компилятора MASM 6.11 в контексте операционной системы MS DOS 6.22!
Я рассмотрел основные структуры MS DOS, спасибо за внимание!
С уважением, push0ret!