This is the past DOS era of the compilation of source code, although has passed, but for the study of the assembly is still helpful, assembly language is just a basic programmer language, most people can grasp, not necessarily in-depth research.
Name free
Page 60,132
Title ' Free---The free spaces on disk '
; Free---a utility to the
; The default or selected disk drive.
;
; Requires Pc-dos or MS-DOS 2.0.
;
; Used in the form:
; a> free [unit:]
; (item in square brackets is optional)
;
; Version 1.0 July 4, 1984
; Copyright (c) 1984 by Ray Duncan
; May is freely reproduced for non-commercial use.
CR Equ 0DH; ASCII Carriage return
LF equ 0ah; ASCII line Feed
Blank Equ 20h; ASCII Space Code
EOM equ ' $ '; end of string marker
; Here we define a dummy segment containing labels
; For the default file control block and the command tail buffer,
; So this main program can access those locations.
;
PSP segment para Public ' PSP '
ORG 05ch
FCB Label byte;d efault file control block
ORG 080h
Command label byte;d efault command buffer
PSP Ends
CSEG segment para public ' CODE '
Assume Cs:cseg,ds:psp,es:data,ss:stack
get_drive proc near; Get drive selection, if any,
; otherwise obtain the identity
; The current disk drive.
; Return Drive (1=a, 2=b, etc.) in AL.
;
MOV AL,FCB; Pick up the drive code, parsed
; by DOS into the default file
;
Or al,al is it the default?
JNZ get_drive1; no, use it
MOV ah,19h; Yes, get the actual current
int 21h;d rive from Pc-dos.
Inc Al; Increment to match FCB code.
GET_DRIVE1:; Return drive code in AL.
Ret
Get_drive ENDP
FREE 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 es,ax; addressable via ES Register.
MOV ah,30h check version of Pc-dos.
int 21h
CMP al,2
Jae Free1;p roceed, DOS 2.0 or greater.
mov dx,offset msg2;D OS 1.x---print error message
mov ax,es and exit. A/fix up DS register
MOV ds,ax so error message is addressable.
JMP free4
Free1:call get_drive to drive selection into DL.
Push es; copy es to DS for remainder
Pop ds;
Assume Ds:data and tell assembler about it.
MOV Dl,al
Add al, ' A '-1; form drive letter from drive code,
mov Outputb,al and put it into the output string.
MOV ah,36h now call DOS to get free disk spaces.
int 21h
CMP ax,-1 was drive invalid?
Je free3; yes,go print error message
;d Rive is OK, so now registers are ...
; Ax=number of sectors per cluster
; Bx=available clusters,
; Cx=number of bytes per sector,
;D x=total clusters per drive.
; Calculate free Spaces:
Mul CX; Sectors per cluster * bytes per sector
;(we assume this won ' t overflow into DX)
Mul BX; then * available clusters
;D X:ax now contains free spaces in bytes.
; SI = last byte to converted string.
mov Si,offset (outputa+9)
MOV cx,10; CX = ten, radix for conversion
Call Bin_to_asc convert free spaces value to ASCII,
MOV dx,offset output
JMP free4 and print it out.
Free3:mov dx,offset msg1 Illegal drive, print error
Free4:mov ah,9;p Rint the string whose address
int 21h; is in DX.
RET; then return to DOS.
Free ENDP
; Convert bit binary value to ASCII string.
;
; Call with Dx:ax = signed bit value
; CX = Radix
; SI = Last byte of area to store resulting string
; (Make sure enough room are available to store
; The string in the radix your have selected.)
;
; Destroys AX, BX, CX, DX, and SI.
;
BIN_TO_ASC proc near; convert Dx:ax to ASCII.
Force storage of at least 1 digit.
mov byte ptr [si], ' 0 '
or DX,DX test sign of bit value,
PUSHF and save sign on stack.
Jns Bin1 Jump if it was positive.
Not DX; It is negative, take 2 ' s complement
not ax; the value.
Add ax,1
ADC dx,0
Bin1:;d ivide The bit value by the radix
; To extract the next digit for the
; forming string.
MOV Bx,ax is the value zero yet?
or BX,DX
JZ bin3 Yes, we are done converting.
Call divide no, divide by radix.
Add bl, ' 0 '; convert the remainder to an ASCII digit.
CMP bl, ' 9 '; we might be converting to hex ASCII,
Jle bin2 Jump If in range 0-9,
Add bl, ' A '-' 9 '-1; correct it if in range a-f.
Bin2:mov [SI],BL Store this character into string.
Dec si; Back up through String,
JMP Bin1 and do it again.
Bin3:; restore sign Flag,
Popf was original value negative?
Jns bin4; no, jump
; Yes,store sign into output string.
mov byte ptr [si], '-'
Bin4:ret to caller.
BIN_TO_ASC ENDP
; General purpose bit by bit unsigned divide.
; This must is used instead of the plain machine unsigned divide
; For cases where the quotient may overflow bits (for example,
; Dividing 100,000 by 2). If called with a zero divisor, this
; Routine returns the dividend unchanged and gives no warning.
;
; Call with Dx:ax = bit dividend
; CX = Divisor
;
; Returns Dx:ax = quotient
; BX = remainder
; CX = divisor (unchanged)
;
Divide proc near; Divide Dx:ax by CX
JCXZ Div1; Exit if divide by zero
Push ax; 0:dividend_upper/divisor
MOV ax,dx
XOR DX,DX
Div CX
MOV bx,ax; BX = Quotient1
Pop ax; Remainder1:dividend_lower/divisor
Div CX
Xchg BX,DX; Dx:ax = Quotient1:quotient2
Div1:ret; BX = Remainder2
Divide ENDP
Cseg ends
Data segment para public ' data '
Output DB CR,LF
Outputa db DUP (blank)
db ' bytes free on drive '
OUTPUTB db ' x: ', Cr,lf,eom
MSG1 DB CR,LF
DB ' That disk drive does not exist. '
DB Cr,lf,eom
MSG2 DB CR,LF
DB ' Requires DOS version 2 or greater. '
DB Cr,lf,eom
Data ends
Stack segment para stack ' stack '
DB DUP (?)
Stack ends
End Free