name dev page 60,132 title 'DEV --- Report installed device drivers' ; DEV --- a utility to report device header information for ; all installed device drivers ; ; Requires PC-DOS or MS-DOS 2.0. ; ; Used in the form: ; A>DEV ; cr equ 0dh ;ASCII carriage return lf equ 0ah ;ASCII line feed blank equ 20h ;ASCII space code eom equ '$' ;end of string marker cseg segment para public 'CODE' assume cs:cseg,ds:data,es:data,ss:stack dev proc far ;entry point from PC-DOS push ds ;save DS:0000 for final xor ax,ax ;return to PC-DOS push ax mov ax,data ;make our data segment mov ds,ax ;addressable via DS and ES. mov es,ax mov ah,30h ;check version of PC-DOS. int 21h cmp al,2 jae dev1 ;proceed, DOS 2.0 or greater. mov dx,offset msg2 ;DOS 1.x --- print error message. jmp dev6 dev1: mov cx,ax ;save DOS version number. mov ah,15 ;now try and open the "NUL" device. mov dx,offset nulfcb int 21h or al,al ;opened successfully? jz dev2 ;yes, jump. mov dx,offset msg1 ;no, print error msg and exit. jmp dev6 dev2: ;Pick up double pointer to device ;driver chain out of reserved ;area in fcb. This area is mapped ;differently in DOS 2.x and DOS 3.x. cmp cl,2 ;is this DOS 2.x? ja dev3 ;no, jump. mov bx,word ptr nulfcb+25 mov es,word ptr nulfcb+27 jmp dev4 dev3: ;come here if DOS 3.0 or greater. mov bx,word ptr nulfcb+26 mov es,word ptr nulfcb+28 dev4: call header ;print sign-on message and ;column headings. dev5: ;trace through the device chain call prdev ;print device header information ;for driver pointed to by ES:BX. ;pick up addr of next header. les bx,dword ptr es:[bx] cmp bx,-1 ;found last one yet? jne dev5 ;no, try next. mov dx,offset msg3 ;yes, print "end of device chain". dev6: mov ah,9 ;print the string whose address int 21h ;is in DX. ret ;then return to DOS. dev endp header proc near ;print out headings for device mov dx,offset hdr ;driver information. mov ah,9 int 21h ret header endp prdev proc near ;print out device driver info. ;ES:BX is pointer to device header, ;which must be preserved. mov ax,es ;convert segment of device header mov di,offset inf1 call hexasc mov ax,bx ;convert offset of device header. mov di,offset inf2 call hexasc mov ax,es:[bx+4] ;get attribute word, save a push ax ;copy of it, then convert it. mov di,offset inf3 call hexasc mov ax,es:[bx+6] ;convert ptr to device strategy. mov di,offset inf4 call hexasc mov ax,es:[bx+8] ;convert ptr to device int handler. mov di,offset inf5 call hexasc ;if not char device, clear out name ;field and set number of units. pop ax ;get back attribute word. test ax,08000h ;is bit 15 = 1 ? jnz prdev7 ;yes, it's character dev, jump. ;no, it's block device. ;set flag to skip device name. mov byte ptr inf8,eom mov al,es:[bx+10] ;pick up number of units. aam ;convert to ASCII decimal and add ax,'00' ;store into output string. mov byte ptr inf7+1,al mov byte ptr inf7,ah ;set type = B for Block mov byte ptr inf6,'B' jmp prdev9 prdev7: ;if char device, move its 8-character ;name into the output string. xor si,si prdev8: mov al,es:[si+bx+10] mov [si+inf8],al inc si cmp si,8 jne prdev8 ;remove # of units field. mov word ptr inf7,' ' ;set type = C for Character. mov byte ptr inf6,'C' prdev9: mov dx,offset inf ;now print device information mov ah,9 ;and exit. int 21h ret prdev endp hexasc proc near ;convert binary word to hex ASCII. ;call with AX=binary value ; DI=addr to store string ;returns AX, CX, DI destroyed. push ax ;save copy of original value. mov al,ah call btoa ;convert upper byte. add di,2 ;increment output address. pop ax call btoa ;convert lower byte. ret ;return to caller. hexasc endp btoa proc near ;convert binary byte to hex ASCII. ;call with AL=binary value ; DI=addr to store string ;returns AX, CX destroyed. mov ah,al ;save lower nibble. mov cx,4 ;shift right 4 positions shr al,cl ;to get upper nibble. call ascii ;convert 4 bits to ASCII equivalent mov [di],al ;store into output string. mov al,ah ;get back lower nibble. and al,0fh call ascii ;convert 4 bits to ASCII mov [di+1],al ;and store into output string. ret ;back to caller. btoa endp ascii proc near ;convert 4 lower bits of AL add al,'0' ;into the equivalent ASCII char. cmp al,'9' ;in the range {0...9,A...F} jle ascii2 ;and return char. in AL. add al,'A'-'9'-1 ;"fudge factor" for range A-F. ascii2: ret ;return to caller. ascii endp cseg ends data segment para public 'DATA' msg1 db cr,lf db 'Failed to open NUL device.' db cr,lf,eom msg2 db cr,lf db 'Requires DOS version 2 or greater.' db cr,lf,eom msg3 db cr,lf db 'End of device chain.' db cr,lf,eom hdr db cr,lf db 'Addr Attr ' db 'Str Int Type Units Name ' db eom inf db cr,lf inf1 db 'XXXX:' ;seg device header inf2 db 'XXXX ' ;offs device header inf3 db 'XXXX ' ;attribute inf4 db 'XXXX ' ;strategy inf5 db 'XXXX ' ;interrupt handler inf6 db 'X ' ;type (block or char) inf7 db 'XX ' ;units (if block device) inf8 db ' ' ;name (if char device) db eom ;fcb to open NUL device nulfcb db 0 ;drive db 'NUL' ;name of NUL device db 8 dup (' ') db 25 dup (0) data ends stack segment para stack 'STACK' db 64 dup (?) stack ends end dev