这篇文章是我写DOS设备驱动程序时临时决定加上的,或者对大家会有帮助。
为了能更好地让大家了解设备驱动程序,在这篇文章里,我打算介绍一个程序给大家,这个程序可以把DOS下的设备驱动程序一个一个地列出来,你可以清楚地看到每个驱动程序的入口地址、设备属性、下一个设备的入口地址、STRATEGY和INTERRUPT的入口地址、以及设备驱动程序的名称,从程序中,你可以清楚地体会到设备驱动程序的单向链表的链接方式,如果你愿意,你还可以深入到任何一个驱动程序中,看它的设备头的结构,看它的STRATEGY和INTERRUPT的代码,总之我希望在我们实际编写驱动程序之前,你能对DOS的设备驱动程序有更深的了解。
我们说过,DOS下的设备驱动程序使用一个单向链表链接起来的,第一个设备是NUL,那么只要我们找到了这个NUL的入口地址,理论上说,我们就可以找到所有的设备驱动程序,但是如何找到这个NUL设备驱动程序呢?DOS能找的到,说明它一定保存了这个地址,所有我们找到它保存的地方就OK了。
得到这个地址我们不得不使用DOS的一条没有公开的调用,功能52h,我们在此仅就我们需要的部分做一个说明,如果那位读者需要这个功能的完整说明,可以和我联系。
int 21h 功能52h:入口:ah=52h 出口:ES:BX指向重要数据清单表
在DOS调用返回的这个清单中偏移22h的地方存放着NUL设备的设备头,一共18个字节,记住是设备头而不是设备头的存放地址,从这个设备头开始就可以完成我们的任务了。
这是我在博客里第一次发布汇编语言的代码,所以我得说一下我的环境,首先这段代码是16位实模式的,用MASM 6.11编译连接的,是个.com的文件格式,如果确实看着有困难,可以轻而易举地在debug下进行跟踪,因为程序太简单所以基本上没有注释。我也不知道该解释什么,好像没有什么需要解释的。
下面给出程序清单:
code segment
assume cs:code, ds:code, es:code, ss:code
org 100h
main proc
jmp begin
ddh struc
ddh_nextOff dw ? ;next device driver after this
ddh_nextSeg dw ?
ddh_attribute dw ? ;attribute of device
ddh_strategy dw ? ;address of strategy routine
ddh_interrupt dw ? ;address of interrupt routine
ddh_devName db 8 dup(?) ;8 bytes device driver name
ddh ends
msg1 db 0dh, 0ah, 0ah, 0ah, 'Device Driver Entry : $'
msg2 db 0dh, 0ah, 0ah, 'Next Device Driver : $'
msg3 db 0dh, 0ah, 'Device Attribute : $'
msg4 db 0dh, 0ah, 'Device Strategy offset : $'
msg5 db 0dh, 0ah, 'Device Interrupt offset : $'
msg6 db 0dh, 0ah, 'Device Driver Name : $'
msg7 db 8 dup(?)
db '$'
begin:
mov ah, 52h
int 21h
add bx, 22h ;+34 bytes.Pointer to DDH
next_ddh:
mov ax, es:[bx].ddh_nextOff
cmp ax, 0ffffh
jz finish
mov dx, offset msg1
mov ah, 09h
int 21h
mov ax, es
call disphex
mov dl, ':'
mov ah, 02h
int 21h
mov ax, bx
call disphex
mov dx, offset msg2
mov ah, 09h
int 21h
mov ax, es:[bx].ddh_nextSeg
call disphex
mov dl, ':'
mov ah, 02h
int 21h
mov ax, es:[bx].ddh_nextOff
call disphex
mov dx, offset msg3
mov ah, 09h
int 21h
mov ax, es:[bx].ddh_attribute
call disphex
mov dx, offset msg4
mov ah, 09h
int 21h
mov ax, es:[bx].ddh_strategy
call disphex
mov dx, offset msg5
mov ah, 09h
int 21h
mov ax, es:[bx].ddh_interrupt
call disphex
mov dx, offset msg6
mov ah, 09h
int 21h
mov si, bx
add si, 10
mov di, offset msg7
mov cx, 8
push es
push ds
pop es
pop ds
rep movsb
push es
push ds
pop es
pop ds
mov dx, offset msg7
mov ah, 09h
int 21h
mov ax, es:[bx].ddh_nextSeg
push ax
mov ax, es:[bx].ddh_nextOff
mov bx, ax
push bx
mov ah, 00h
int 16h
pop bx
pop es
jmp next_ddh
finish:
ret
main endp
;************************************
;* Display a HEX digit
;* input: ax=digit output: none
;************************************
disphex proc
push bx
push es
mov cx, 4
xchg ah, al
mov bl, al
shr al, cl
shl bl, cl
or al, bl
mov bl, ah
shr ah, cl
shl bl, cl
or ah, bl
again:
push cx
push ax
and al, 0fh
cmp al, 9
ja disphex1
add al, 30h
jmp disphex2
disphex1:
add al, 37h
disphex2:
mov dl, al
mov ah, 02h
int 21h
pop ax
mov cl, 4
shr ax, cl
pop cx
loop again
mov dl, 'h'
mov ah, 02h
int 21h
pop es
pop bx
ret
disphex endp
code ends
end main
评论