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