home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / DOS_HELP / ADVMSDOS.ZIP / FREE.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-06-19  |  6.1 KB  |  217 lines

  1.         name    free
  2.         page    60,132
  3.         title   'FREE --- Report free space on disk'
  4.  
  5. ; FREE --- a utility to report free space on
  6. ;          the default or selected disk drive.
  7. ;
  8. ; version 1.0   July 4, 1984 
  9. ; Copyright (c) 1984 by Ray Duncan
  10. ; Requires PC-DOS or MS-DOS 2.0.
  11. ;
  12. ; Used in the form:
  13. ;
  14. ;     A> FREE  [unit:] 
  15. ;
  16. ; (item in square brackets is optional)
  17. ;
  18. ; To assemble, link, and convert this program into 
  19. ; an EXE file, follow these steps:
  20. ;
  21. ;    C>MASM FREE;
  22. ;     C>LINK FREE;
  23. ;
  24.  
  25. cr      equ     0dh             ;ASCII carriage return
  26. lf      equ     0ah             ;ASCII line feed
  27. blank    equ    20h        ;ASCII space code
  28. eom    equ    '$'        ;end of string marker
  29.  
  30.  
  31. ; Here we define a dummy segment containing labels
  32. ; for the default file control block and the command tail buffer,
  33. ; so that the main program can access those locations.
  34. ;
  35. psp    segment para public 'PSP'  
  36.  
  37.     org    05ch
  38. fcb    label    byte        ;default file control block
  39.  
  40.     org    080h
  41. command    label    byte        ;default command buffer
  42.  
  43. psp    ends
  44.  
  45.  
  46. cseg    segment    para public 'CODE'
  47.  
  48.     assume    cs:cseg,ds:psp,es:data,ss:stack
  49.  
  50.  
  51. get_drive proc    near        ;get drive selection, if any,
  52.                 ;otherwise obtain the identity
  53.                 ;of the current disk drive.
  54.                 ;Return drive (1=A, 2=B, etc) in AL.
  55.                 ;
  56.     mov     al,fcb            ;Pick up the drive code, parsed 
  57.                 ;by DOS into the default file
  58.                 ;control block.
  59.     or    al,al        ;Is it the default?
  60.     jnz    get_drive1    ;no, use it
  61.     mov    ah,19h        ;Yes, get the actual current
  62.     int    21h        ;drive from PC-DOS.
  63.     inc     al        ;Increment to match FCB code.
  64. get_drive1:            ;Return drive code in AL.
  65.     ret
  66. get_drive endp
  67.  
  68.  
  69. free     proc    far             ;entry point from PC-DOS
  70.  
  71.         mov     ax,data         ;make our data segment
  72.         mov     es,ax           ;addressable via ES register.
  73.         mov     ah,30h        ;check version of PC-DOS.    
  74.         int     21h
  75.         cmp     al,2
  76.         jae     free1        ;proceed, DOS 2.0 or greater.
  77.         mov     dx,offset msg2  ;DOS 1.x --- print error message
  78.     mov    ax,es        ;and exit. First fix up DS register 
  79.     mov    ds,ax        ;so error message is addressable.
  80.     jmp    free4
  81.  
  82. free1:  call    get_drive     ;get drive selection into DL.
  83.     push    es        ;copy ES to DS for remainder
  84.     pop    ds        ;of the program...
  85.     assume    ds:data        ;and tell assembler about it.
  86.     mov    dl,al        
  87.     add    al,'A'-1    ;form drive letter from drive code,
  88.     mov    outputb,al    ;and put it into the output string. 
  89.     mov    ah,36h        ;now call DOS to get free disk space.
  90.     int    21h
  91.     cmp    ax,-1        ;was drive invalid?
  92.     je    free3        ;yes,go print error message
  93.                 ;drive was ok, so now registers are...
  94.                 ;AX=number of sectors per cluster
  95.                 ;BX=available clusters,
  96.                 ;CX=number of bytes per sector,
  97.                 ;DX=total clusters per drive.
  98.                 ;calculate free space:
  99.     mul    cx        ;sectors per cluster * bytes per sector
  100.                 ;(we assume this won't overflow into DX)
  101.     mul    bx        ;then * available clusters 
  102.  
  103.                 ;DX:AX now contains free space in bytes.
  104.                 ;SI = last byte address for converted string.
  105.     mov    si,offset (outputa+9)
  106.     mov    cx,10        ;CX = 10, radix for conversion
  107.     call    bin_to_asc    ;convert free space value to ASCII,
  108.     mov    dx,offset output
  109.     jmp    free4        ;and print it out.
  110.  
  111. free3:  mov     dx,offset msg1  ;illegal drive, print error
  112.  
  113. free4:    mov    ah,9        ;print the string whose address
  114.     int    21h        ;is in DX.
  115.     mov     ax,4c00h        ;then return to DOS 
  116.     int    21h
  117.  
  118. free   endp
  119.  
  120.  
  121. ; Convert 32 bit binary value to ASCII string.
  122. ;
  123. ; Call with  DX:AX = signed 32 bit value
  124. ;         CX    = radix
  125. ;            SI    = last byte of area to store resulting string
  126. ;                 (make sure enough room is available to store
  127. ;              the string in the radix you have selected.)
  128. ;
  129. ; Destroys AX, BX, CX, DX, and SI.
  130. ;
  131. bin_to_asc proc    near        ;convert DX:AX to ASCII.
  132.                 ;force storage of at least 1 digit.
  133.     mov    byte ptr [si],'0' 
  134.     or    dx,dx        ;test sign of 32 bit value,
  135.     pushf            ;and save sign on stack.
  136.     jns    bin1        ;jump if it was positive.
  137.     not    dx        ;it was negative, take 2's complement
  138.     not    ax        ;of the value. 
  139.     add    ax,1
  140.     adc    dx,0
  141. bin1:                ;divide the 32 bit value by the radix 
  142.                 ;to extract the next digit for the
  143.                 ;forming string.
  144.     mov    bx,ax        ;is the value zero yet?
  145.     or    bx,dx
  146.     jz    bin3        ;yes, we are done converting.
  147.     call    divide        ;no, divide by radix.
  148.     add    bl,'0'        ;convert the remainder to an ASCII digit.
  149.     cmp    bl,'9'        ;we might be converting to hex ASCII,
  150.     jle    bin2        ;jump if in range 0-9,
  151.     add    bl,'A'-'9'-1    ;correct it if in range A-F.
  152. bin2:    mov    [si],bl        ;store this character into string.
  153.     dec    si        ;back up through string,
  154.     jmp    bin1        ;and do it again.
  155. bin3:                ;restore sign flag,
  156.     popf            ;was original value negative?
  157.     jns    bin4        ;no, jump
  158.                 ;yes,store sign into output string.
  159.     mov    byte ptr [si],'-'
  160. bin4:    ret            ;back to caller.
  161. bin_to_asc endp
  162.  
  163.  
  164. ; General purpose 32 bit by 16 bit unsigned divide.
  165. ; This must be used instead of the plain machine unsigned divide
  166. ; for cases where the quotient may overflow 16 bits (for example,
  167. ; dividing 100,000 by 2).  If called with a zero divisor, this
  168. ; routine returns the dividend unchanged and gives no warning.
  169. ;
  170. ; Call with DX:AX = 32 bit dividend
  171. ;           CX    = divisor
  172. ;
  173. ; Returns   DX:AX = quotient
  174. ;           BX    = remainder
  175. ;        CX    = divisor (unchanged)
  176. ;
  177. divide    proc    near        ; Divide DX:AX by CX
  178.     jcxz    div1        ; exit if divide by zero
  179.     push    ax        ; 0:dividend_upper/divisor
  180.     mov    ax,dx
  181.     xor    dx,dx
  182.     div    cx
  183.     mov    bx,ax        ; BX = quotient1
  184.     pop    ax        ; remainder1:dividend_lower/divisor
  185.     div    cx
  186.     xchg    bx,dx        ; DX:AX = quotient1:quotient2
  187. div1:    ret            ; BX = remainder2
  188. divide    endp
  189.  
  190. cseg    ends
  191.  
  192.  
  193. data    segment para public 'DATA'
  194.  
  195. output        db    cr,lf
  196. outputa        db    10 dup (blank)
  197.         db    ' bytes free on drive '
  198. outputb        db    'x:',cr,lf,eom
  199.  
  200. msg1            db      cr,lf
  201.                 db      'That disk drive does not exist.'
  202.                 db      cr,lf,eom
  203.  
  204. msg2            db      cr,lf
  205.                 db      'Requires DOS version 2 or greater.'
  206.                 db      cr,lf,eom
  207.  
  208. data    ends    
  209.  
  210.  
  211. stack   segment para stack 'STACK'
  212.         db      64 dup (?)
  213. stack   ends
  214.  
  215.         end     free
  216.