📄 dos.asm
字号:
cEnd
;*--------------------------------------------------------------------------
;*
;* LONG DosDiskFreeSpace(Drive)
;*
;* note:
;* Drive == 0 default
;* Drive == 1 A
;* Drive == 2 B
;*--------------------------------------------------------------------------
; Returns the number of bytes free in DX:AX
cProc DosDiskFreeSpace, <FAR, PUBLIC>
ParmW Drive
cBegin
mov dx,Drive
mov ah,36h ; Set Current Drive
int 21h
cmp ax, 0ffffh ; bogus drive?
je error
mul cx ;
mul bx
jmp done ; DX:AX contains free space
error:
mov dx, ax ; return dx:ax = -1L
done:
cEnd
;*--------------------------------------------------------------------------*
;* *
;* BOOL DosIsRemote(int); *
;* *
;* ENTRY: Word, iPDrive: must be of the form ( logical volume A = 0 ) *
;* Physical Drive Spec. B = 1 *
;* C = 2 *
;* ect. *
;* EXIT: BOOL returned in AX Remote = Remote *
;* False = Local *
;* not_supported *
;* *
;* DESTROYS: AX. (preserves all registers except AX for return value) *
;* *
;* AUTHOR: MC *
;* *
;*--------------------------------------------------------------------------*
cProc DosIsRemote, <FAR, PUBLIC>, <BX,CX,DX,SI,DI,ES,DS>
ParmW iPDrive ; Int Physical drive spec 0 - 25
localV local_name, 16d ; Buffer to hold redirected local name.
localV net_name, 128d ; Buffer to hold remote device name.
localV remote_list, 42d ; Buffer, will be filled with list of
; redirected local device names.
cBegin
; First, we need to make a list of remote devices (logical Volumes)
; I have to use DOS call int 21h/5f02h because DOS call int 21h/4409h
; is not reliable under DOS versions 4.00 and 4.01. (IBM fuck-up).
xor cx,cx
xor dx,dx
next_entry:
mov bx,cx ; CX = redirection list index.
mov ax,ss ; Load segs for stack vars.
mov es,ax
mov ds,ax
mov ax,5f02h ; func 5f/02 Get redirection list.
lea si,local_name ; ds:si = local_name
lea di,net_name ; es:di = net_name
push cx ; save CX
push dx ; save DX
int 21h
pop dx ; restore DX
pop cx ; restore CX
jc check_support ; error, not supported or end of list.
cmp bl,04h ; Is redirected device a drive ?
jne not_a_drive ; If not, we don't care !
mov al,byte ptr ds:[si] ; Grab volume name.
sub al,41h ; Convert to volume number A=0 ect.
lea di,remote_list ; get a pointer to our remote list.
add di,dx ; DX is index into list of devices.
mov byte ptr es:[di],al ; save remote device into out list.
inc dx ; Increment list index pointer.
not_a_drive:
inc cx ; CX = redirection list index.
jmp short next_entry
check_support:
cmp ax,12h ; AX = 12h means end of redir list !
jne Game_Over_Man ; If not then soooo long.
lea di,remote_list
add di,dx ; DX is index into list of devices.
mov byte ptr es:[di],0ffh ; Terminate list.
;
; Is the drive remote ?
; See if it matches any entries in list of redirected devices.
;
lea di,remote_list ; pointer to list of redirected drives.
mov bx,iPDrive ; Grab the parameter.
next_in_list:
cmp byte ptr es:[di],0ffh ; Are we at the end of the redir list ?
jne keep_checking
mov ax,FALSE ; Indicate Volume not remote !
jmp IsRemoteDone
keep_checking:
xor cx,cx
mov cl,byte ptr es:[di]
cmp bx,cx
je Found_Remote
inc di
jmp short next_in_list
Game_Over_Man:
mov ax,NOT_SUPPORTED ; Indicate no support in return value.
jmp short IsRemoteDone
Found_Remote:
mov ax,REMOTE ; Indicate Volume is remote !
IsRemoteDone:
cEnd
;*--------------------------------------------------------------------------*
;* *
;* int GetFixedDisks(int foo[26]); *
;* *
;* Returns the number of active LOCAL FIXED disk drives in the system AND *
;* puts their indexes into rgiDrive[]. *
;* *
;* ENTRY: Pointer to array of 26 integers. *
;* *
;* EXIT: Returns the number of active LOCAL FIXED disk drives in the *
;* system puts their indexes into rgiDrive[]. *
;* *
;* DESTROYS: AX. (preserves all registers except AX for return value) *
;* *
;* AUTHOR: MC *
;* *
;*--------------------------------------------------------------------------*
cProc GetFixedDisks, <FAR, PUBLIC>, <BX,SI,DI>
ParmW rgiDrive
localW cRealDrives
cBegin
; Preserve the current drive setting.
call GetCurrentDrive
mov di,ax ; Save original drive.
xor si,si ; SI = iLogDrives = zero
mov cRealDrives,si ; cRealDrives = zero
GDCLoop:
; Attempt to set the current drive to SI.
push si
call SetCurrentDrive
; Did it actually work?
;
call GetCurrentDrive
cmp ax,si
jnz GDC300 ; Nope, skip
;
; Is the drive remote ?
;
push si
call DosIsRemote
cmp ax,REMOTE ; Is the drive remote ?
je GDC300
; Here we have found the drive is not Remote or we cannot tell if
; the drive is remote so lets find out if
; its removable before we add it to the cRealDrives list.
mov ax,4408h ; IOCTL is removeable
mov bx,si
inc bx ; map from 0=A to 1=A
int 21h
jc check_call ; error, skip
or al,al
jz GDC300 ; removeable, skip
; Store the drive number in rgiDrive[]
mov ax,rgiDrive
mov bx,cRealDrives
inc cRealDrives
shl bx,1
add bx,ax
mov word ptr [bx],si
jmp short GDC300
; We have a problem if IOCTL int 21h/4408h is not supported because then
; we have know way of knowing weather or not the machine in question really
; does have a fixed disk connected. Therefore, in this case, we'll give the
; user the benifit of the doubt and let them continue to install windows.
check_call:
cmp ax,1 ; Is this call supported ?
jnz GDC300 ; If yes, continue on normally.
mov cRealDrives,1 ; If not, we better indicate we have
jmp short no_chance ; a fixed disk and return.
GDC300:
inc si
cmp si,26 ; Loop through all 26 drives
jne GDCLoop
no_chance:
; Restore the original current drive.
push di ; Put pram on stack for call.
call SetCurrentDrive ; Restore original drive.
mov ax,cRealDrives ; Return num local drives in AX.
cEnd
;*--------------------------------------------------------------------------*
;* *
;* BOOL DosRemoveable(char); *
;* *
;* ENTRY: Word iLDrive - Logical drive spec. A - Z. (case does not matter) *
;* *
;* EXIT: BOOL Returns TRUE if media is removable. False if Remote or fixed *
;* *
;* DESTROYS: AX. (preserves all registers except AX for return value) *
;* *
;* AUTHOR: MC *
;* *
;*--------------------------------------------------------------------------*
cProc DosRemoveable, <FAR, PUBLIC>, <BX>
ParmW iLDrive ; Logical Drive spec A - Z.
cBegin
mov bx,iLDrive ; Grab the parameter.
or bx,20h ; case insensitive.
sub bx,'a' ; map to A=0
push bx ; Put param on stack for call.
call DosIsRemote ; Find out if logical volume is remote
or ax,ax ; check IsRemote return ?
jnz Remote_Or_Removable ; False ( 0 ) means local.
; Now we have found the volume is local, we can check to
; see if it's removable or not.
mov ax,4408h ; IOCTL is removeable
inc bx ; Map from A=0 to A=1 ...
int 21h
jc Remote_Or_Removable ; error, skip
or al,al
jnz Remote_Or_Removable ; NOT removeable
inc ax
jnz ir_exit
Remote_Or_Removable:
xor ax,ax ; Return FALSE for remote or removable.
ir_exit: ; Finished.
cEnd
;*--------------------------------------------------------------------------*
;* *
;* MyReadWriteSector() - *
;* *
;*--------------------------------------------------------------------------*
; Uses INT 13h to read/write an absolute sector.
cProc MyReadWriteSector, <PUBLIC, FAR>, <SI,DI>
ParmD lpBuffer
ParmW Function ; 02 for Read and 03 for Write
ParmW Drive
ParmW Cylinder
ParmW Head
ParmW Count
LocalW wRetryCount
cBegin
; Retry this operation three times.
mov wRetryCount,4
MRWS_TryAgain:
mov ax,Count ; AL = Number of sectors
mov ah,byte ptr Function ; AH = Function #
mov ch,byte ptr Cylinder ; CH = Starting Cylinder
mov cl,1 ; CL = Starting Sector
mov dx,Drive ; DL = INT 13h drive designation
mov dh,byte ptr Head ; DH = Head #
les bx,lpBuffer ; ES:BX = Buffer
int 13h
mov ax, 1 ; success
jnc MRWS_End_success ; Problems?
dec wRetryCount ; Yup, retry
jz MRWS_End_fail ; Are we out of retries?
xor ah,ah ; Nope, reset the disk
mov dx,Drive
int 13h
jmp short MRWS_TryAgain
MRWS_End_fail:
xor al,al ; AH contains the error code, if any.
MRWS_End_success:
cEnd
;*--------------------------------------------------------------------------*
;* *
;* GetCurrentVolume() - *
;* *
;*--------------------------------------------------------------------------*
; Returns ZERO if successful.
cProc GetCurrentVolume, <FAR, PUBLIC>, <SI, DI>
ParmD lpszVol
cBegin
push ds
; Set the DTA
mov dx,offset DGROUP:DTA
mov ah,1Ah ; Set DTA
int 21h
; Get the current volume name.
mov dx,offset DGROUP:VolExtendedFCB
mov ah,11h ; Search for First Entry
int 21h
test al,al
jnz GVNoVol
; Copy volume name into buffer.
les di,lpszVol
mov al,'['
stosb
cld
mov si,offset DGROUP:DTA + 8
mov cl,11
GVLoop:
lodsb
cmp al,' '
jz GVCont
stosb
loop GVLoop
GVCont:
mov al,']'
stosb
; NULL terminate.
xor ax,ax
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -