home *** CD-ROM | disk | FTP | other *** search
- ;-----------------------------------------------------------------------;
- ; This is the main source code for DIRM v1.3, a FAST! directory lister. ;
- ; It is the copyrighted property of Michael P. Rice. (c) 1990. ;
- ; This source code is NOT in the public domain and cannot be used ;
- ; commercially without permission. Completed 2-November-1990. ; ;
- ;-----------------------------------------------------------------------;
- .model small
-
- .data
- ;-----------------------------------------------------------------------;
- ; The following table is used in the write_time procedure. The bits ;
- ; are used as follows: Bits 6,7 Unused ;
- ; 5 Space flag 0=off 1=on ;
- ; 4 Am\Pm flag 0=am 1=pm ;
- ; 3,2,1,0 Hour to print ;
- ;-----------------------------------------------------------------------;
- time_table db 0ch,21h,22h,23h,24h,25h,26h,27h,28h,29h,0ah,0bh
- db 1ch,31h,32h,33h,34h,35h,36h,37h,38h,39h,1ah,1bh
-
- ;-----------------------------------------------------------------------;
- ; This is a simple table to determine AM/PM for write_time. ;
- ;-----------------------------------------------------------------------;
- am_pm_table db 'a','p'
-
- def_filespec db '*.*',0
- volumespec db '*.*',0
- filespec db 13 dup (0)
- filespec2 db 13 dup (0) ; SS
-
- ;-----------------------------------------------------------------------;
- ; These are used for attribute processing. Default is attributes will ;
- ; not be printed. File mask 31h means hidden and system files are not ;
- ; show in the directory. When attributes are on, system and hidden ;
- ; files are shown with mask=37h ;
- ;-----------------------------------------------------------------------;
- attrib_on db 0
- attrib_mask dw 0031h
-
- ;-----------------------------------------------------------------------;
- ; These are the ASCIIZ string data messages used in the program. ;
- ;-----------------------------------------------------------------------;
- volumemess1 db 'Volume in Drive ',0
- volumemess2 db ' is ',0
- volumemess3 db ' has no label.',0
- colon db ':',0 ;SS
- dirmess1 db "DIRM v1.3 Directory of ",0
- dirmess2 db ' Filespec: ',0
- dir_braces db ' <DIR> ',0
- moremessage db 'Press any key to continue',0
- trailermess0 db ' bytes in ',0
- trailermess1 db ' File(s)',0
- trailermess2 db ' bytes free. ',0
- illegalswitch db 'Usage: dirm [d:][path specification] [/switches]',0
- legalswitches db ' /w wide mode /p page at a time /a show attribs',0
- nofoundpath db 'Unknown Path | ',0
- nofoundswitch db 'Illegal Switch | ',0
-
- ;-----------------------------------------------------------------------;
- ; Flags used to indicate the use of a switches /p /w /r. ;
- ;-----------------------------------------------------------------------;
- page_flag db 0
- recursive_flag db 0
- wide_flag db 0
-
- ;-----------------------------------------------------------------------;
- ; Flags used in PSP processing to detect the need for default params. ;
- ;-----------------------------------------------------------------------;
- drive_set db 0
- directory_set db 0
-
- ;-----------------------------------------------------------------------;
- ; This is used to keep a count of the files in the directory, not ;
- ; including directory entries. ;
- ;-----------------------------------------------------------------------;
- files dw 0
-
- ;-----------------------------------------------------------------------;
- ; This keeps track of lines printed for the /p page switch. It is set ;
- ; initially to 3 to keep the header on the screen. ;
- ;-----------------------------------------------------------------------;
- filecount db 3
-
- ;-----------------------------------------------------------------------;
- ; These are where the drive numbers are stored when a change is needed. ;
- ;-----------------------------------------------------------------------;
- startdrive db 0
- tempdrive db 0
-
- ;-----------------------------------------------------------------------;
- ; These are directory specifications used with INT 21h BIOS calls. ;
- ;-----------------------------------------------------------------------;
- root db '\',0
- directory db '\'
- db 64 dup (?)
- tempdir db '\'
- db 64 dup (?)
-
- ;-----------------------------------------------------------------------;
- ; This is where the filesizes of matching files are accumulated. ;
- ;-----------------------------------------------------------------------;
- accum_filesize dd 00000000h
-
- ;-----------------------------------------------------------------------;
- ; This is the field to add commas to the filesize, bytes free numbers ;
- ;-----------------------------------------------------------------------;
- p_field db ' , , , ',0
-
-
- .data?
-
- ;-----------------------------------------------------------------------;
- ; This is the data area used for the disk DTA - Disk Transfer Area. ;
- ;-----------------------------------------------------------------------;
- Reserved db 21 dup (?) ;Reserved
- FAttrib db 1 dup (?) ;file's Attribute
- FTime db 2 dup (?) ;file's time stamp
- FDate db 2 dup (?) ;file's date stamp
- FSize db 4 dup (?) ;file's size
- FName db 13 dup (?) ;ASCIIZ file name
-
- ;-----------------------------------------------------------------------;
- ; Area to move the command line PSP area switches, directory specs, etc ;
- ;-----------------------------------------------------------------------;
- PSPBytes db 1 dup (?)
- PSPSpace db 1 dup (?)
- PSPArea db 7Eh dup (?)
-
- ;-----------------------------------------------------------------------;
- ; Just what it says: holds the current filesize that will be added to ;
- ; the accumulated file size. ;
- ;-----------------------------------------------------------------------;
- current_filesize db 4 dup (?)
-
- .stack
-
- .code
-
- EXTRN send_crlf:proc, write_string:proc, write_char:proc
- EXTRN goto_xy:proc, init_write_char:proc
- EXTRN SCREEN_X:byte, goto_col:proc
- PUBLIC disk_dir
- ;-----------------------------------------------------------------------;
- ; This is a C callable function to display a disk directory. ;
- ;-----------------------------------------------------------------------;
- disk_dir PROC
- mov dx,ds
- mov ax,@data
- mov ds,dx ;Both DS and ES point to the data
- mov es,ax
-
- mov si,80h ;Move the PSP into Memory
- mov di,OFFSET PSPBytes
- mov cx,80h
- rep movsb
- mov ds,ax
-
- call init_write_char ;Determine screen memory
-
- mov ah,19h
- int 21h ;Get current drive
- mov startdrive,al ;Save current drive
- mov tempdrive,al
-
- call process_psp ;Process command switches
- call adjust_filespec ;Make filespec = filespec.*
-
- mov ah,47h ;Save the new temporary directory
- mov si,OFFSET tempdir+1
- mov dl,0
- int 21h
-
- call send_crlf
-
- mov dx,OFFSET Reserved ;Set up a DTA
- mov ah,1ah
- int 21h
-
- call write_volume ;Write Volume Message/Volume
- call send_crlf
-
- mov dx,OFFSET filespec ;Load in the currentfilespec
- mov cx,attrib_mask ;Search for normal files
- mov ah,4eh
- int 21h ;Get first filename
- mov di,0
- jae printf ;Print the entry
- jmp exit_disk_dir ;No entries on DISK!
-
- printf:
-
- cmp wide_flag,0 ;Is wide flag being used?
- jne wide_files ;If so, go process in wide mode
- cmp page_flag,0 ;If page flag isn't set we skip
- je skip_page_stuff ; over the page processing
-
- cmp filecount,24 ;Otherwise, Do we have 24 lines yet?
- jne increment_filecount ;If not, increment lines
- call process_endpage ;If so, do hold processing
- jmp skip_page_stuff ; and don't increment
- increment_filecount:
- inc filecount ;Increment lines=files
- skip_page_stuff:
- mov bx,OFFSET FAttrib ;Check for directories
- mov cx,[bx] ;Move the attrib into CX
- and cx,0010h ;Check for directory
- mov dx,OFFSET FName ;Write name from DTA
- cmp cx,0
- jnz just_write_dir
- call write_first ;Write first part of file name
- ; i.e. part before the '.'
- push dx ;Save offset returned by write_first
- mov dl,9 ;Goto column 10 for extension printing
- call goto_col
- pop dx ;Get back the extension's OFFSET
- just_write_dir:
- call write_string ;Write the extension or if
- ; it is a directory write it all
-
- mov dl,12
- call goto_col ;Move to column 13
- cmp cx,0 ;If CX is 0, it is not a directory
- jz fsize_stuff ;So want to print the filesize info
-
- mov dx,OFFSET dir_braces ;Otherwise print a <DIR> message
- call write_string ;instead of a filesize
- jmp date_stuff ;Do date stuff, skip wide stuff
-
- wide_files:
- mov bx,OFFSET FAttrib ;Check for director so we don't
- mov cx,[bx] ;include it in the file count
- and cx,0010h
- cmp cx,0 ;If CX is 0, it is not a directory
- jnz no_inc ;So don't increment the file count
- inc files ;Add one to file count
- no_inc:
- cmp di,80 ;If we are at col 64 want to do a CRLF
- je newline
- mov dx,di ;Move to the right column
- call goto_col ;which is 16 more than the last column
- jmp write_it ;write the file or directory name
- newline:
- call send_crlf ;Send a carriage return/linefeed and
- inc filecount ;Increment lines count=file*5
- cmp page_flag,0 ;If not in wide and page modes
- je no_more_prompt ; don't check for number of lines
- cmp filecount,24 ;Do we have 24 lines yet?
- jne no_more_prompt ;If not, don't do hold processing
- call process_endpage ;If so, do hold processing
- no_more_prompt:
- mov di,0 ;Set current column to 0
- write_it:
- mov dx,OFFSET FName ;Write the name
- call write_string
- add di,16 ;Add 16 to column counter
- jmp more_files ;Go see if there are more files
-
- printf_link:
- jmp printf ;Too large routines cause this noise
-
- fsize_stuff:
- inc files ;Increment number of files
- mov bx,OFFSET FSize ;Get Offset in file size area
- mov si,[bx] ;Get LSBs of file size
- mov di,[bx+2] ;Get MSBs of file size
- call tally_files ;Add to file byte accumulator
-
- call bin_to_ascii ;Convert and print in decimal
-
- mov dl,' ' ;Move one column forward
- call write_char
- date_stuff:
- mov dx,OFFSET FDate ;Set to date in DTA
- call write_date ;Write the date out
-
- mov dl,' ' ;Move one column forward
- call write_char
-
- mov dx,OFFSET FTime
- call write_time ;Write the time out
-
- mov dl,' ' ;Write the space
- call write_char
-
- cmp attrib_on,0 ;Was the attrib '/a' switch used?
- je no_attribs ;If not, skip this code
- mov dx,OFFSET FAttrib
- call write_attributes ;Write the attributes after the time
- no_attribs:
- call send_crlf
-
- more_files:
- mov ah,4fh ;Get next filename
- int 21h
- jae printf_link ;Print entry if exists
- ;Or exit, if done
-
- exit_disk_dir:
- cmp wide_flag,0 ;If wide mode is active no CRLF
- je no_crlf ;is needed after each filename
- call send_crlf
- mov dl,8 ;Goto column 9 for wide mode trailer
- call goto_col
- no_crlf:
- call write_trailer ;Write # files, etc
-
- mov dl,startdrive
- mov ah,0eh ;Restore correct drive
- int 21h
-
- mov dx,OFFSET directory ;Restore correct subdirectory
- mov ah,3bh
- int 21h
-
- call send_crlf
-
- mov ah,4ch
- int 21h ;Exit to DOS
-
- disk_dir ENDP
-
- public adjust_filespec
- ;-----------------------------------------------------------------------;
- ; This procedure makes filespec match all filespec.* files. If you ;
- ; don't want this for some reason you can remove this procedure and its ;
- ; call without harm. It was added in version 1.1 for COMMAND.COM com- ;
- ; patibility. ;
- ;-----------------------------------------------------------------------;
- adjust_filespec PROC
- push ax ;Save registers
- push cx
- push di
- push si
-
- mov si,OFFSET filespec ;Find beginning of set filespec
- lodsb ;Load a byte SS
- cmp al,'.' ;See if it is a period SS
- je first_period ; If it is go to first_period SS
- dec si ;Go back to start of filespec SS
-
- loopback:
- lodsb ;Get a byte
- cmp al,'.' ;Check if it has an extension
- je ext_found ; If it does branch out
- cmp al,0 ; If end, no extension found
- je no_ext_found
- jmp loopback ;Keep trying
-
- first_period: ; SS
- mov di,OFFSET filespec2 ;Builds new specs in filespec2 SS
- mov si,OFFSET def_filespec ;Only if filespec given starts SS
- mov cx,1 ;With a period '.' SS
- rep movsb ;Basically just adds an '*' SS
- mov si,OFFSET filespec ;Before the specs given SS
- mov di,OFFSET filespec2+1 ; SS
- mov cx,4 ; SS
- rep movsb ; SS
- mov si,OFFSET filespec2 ;Puts filespec2 into SS
- mov cx,5 ; filespec SS
- call set_filespec ; SS
- jmp loopback ;Goes to loopback SS
-
- ext_found:
- lodsb ;See if it is just a .
- cmp al,0
- dec si ;Set si for no_ext_found
- je no_ext_found
- jmp exit_adjust_filespec
-
- no_ext_found:
- dec si
- mov di,si ;Move ".*",0 into filespec
- mov si,OFFSET def_filespec+1
- mov cx,3
- rep movsb
-
- exit_adjust_filespec:
- pop si ;Restore registers and exit
- pop di
- pop cx
- pop ax
- ret
-
- adjust_filespec ENDP
-
- public process_endpage
- extrn clear_to_end_of_line:proc
- ;-----------------------------------------------------------------------;
- ; This procedure initializes the filecount and prints the MORE message ;
- ; then waits for a keypress and sends a carriage return and returns. ;
- ;-----------------------------------------------------------------------;
- process_endpage PROC
- mov filecount,0 ;Initialize the file count
- mov dx,OFFSET moremessage ; 'Press any key to continue'
- call write_string
- mov ah,02h ;Move cursor to correct position
- mov bh,0 ;Page 0
- mov dx,1819h ;Row 24, Col 25
- int 10h
- mov ah,07h ;Wait for keypress, don't echo it
- int 21h
- mov dl,0 ;Go back to column zero
- call goto_col
- call clear_to_end_of_line ;Erase 'Press any key' message
- ret ; and return
- process_endpage ENDP
-
-
- public write_first
- ;-----------------------------------------------------------------------;
- ; This procedure is used to print the first part of a file name. It ;
- ; expects DS:DX to point to the filename. For example if a filename is ;
- ; defined as NAME db 'FIRST.EXT',0 this will print FIRST and leave ;
- ; DX pointing to the first letter after the . So the extension can be ;
- ; printed with a normal ASCIIZ print routine with DX the OFFSET. ;
- ;-----------------------------------------------------------------------;
- write_first proc
- push ax ;Save registers and Flags
- push si
- pushf
-
- cld ;Increment of LODS,STOS
- mov si,dx ;Get OFFSET
-
- first_loop:
- lodsb ;Get a byte
- cmp al,'.' ;Is it the extension divider?
- jz end_of_first ;If yes, we've found the end
- cmp al,0 ;Is it the end of the filename?
- jz end_of_first1 ;If yes, there is no extension
- mov dl,al ;Otherwise, write the character
- call write_char
- jmp first_loop
- end_of_first1:
- dec si ;Move back if end (May not be needed)
- end_of_first:
- mov dx,si ;Save the OFFSET
- popf ;Restore flags and registers
- pop si
- pop ax
- ret
- write_first ENDP
-
-
- public process_psp
- ;-----------------------------------------------------------------------;
- ; This procedure takes care of the DOS command line switches. ;
- ;-----------------------------------------------------------------------;
- process_psp proc
- push ax ;Save the friggin' registers
- push bx
- push cx
- push dx
- push di
- push si
- push bp
-
- mov bx,OFFSET PSPBytes
- mov cl,[bx] ;Get number of characters of info
-
- and cx,00ffh ;Make sure CL is zero
- jcxz exit_default_link ;If there are no characters
-
- dec cl ;Remove leading space
-
- mov bx,cx ;Place a zero after last
- add bx,OFFSET PSPArea ;byte in PSP header
- xor al,al
- mov [bx],al
-
- cld ;Increment on LODS commands
- mov si,OFFSET PSPArea
-
- loop1:
- jcxz exit_check_link
- dec cl
- lodsb ;Loop through any leading spaces
- cmp al,' '
- je loop1
- cmp al,'/' ;Check for switch characters
- je process_switches
- cmp al,'\' ;Check for full path indicator
- je process_full_path
- jmp process_rel_path ;Must be relative path or drivespec
-
- ;-----------------------------------------------------------------------------
- exit_default_link:
- jmp exit_default
- exit_check_link:
- jmp exit_check
-
- process_switches:
- lodsb
- dec cl
- cmp al,'a' ;Check for ATTRIBUTE switch
- je a_switch
- cmp al,'A'
- je a_switch
- cmp al,'r' ;Check for RECURSIVE switch
- je r_switch
- cmp al,'R'
- je r_switch
- cmp al,'p' ;Check for PAGE switch
- je p_switch
- cmp al,'P'
- je p_switch
- cmp al,'w' ;Check for WIDE switch
- je w_switch
- cmp al,'W'
- je w_switch
- jmp error ;Illegal damn switch
-
- a_switch:
- mov attrib_mask,37h ;Look also for hidden and system files
- mov attrib_on,1 ;Set attrib flag on
- jmp loop1
- r_switch:
- mov recursive_flag,1 ;Set recursive flag on
- jmp loop1
- p_switch:
- mov page_flag,1 ;Set page flag on
- jmp loop1
- w_switch:
- mov wide_flag,1 ;Set wide flag on
- jmp loop1
-
- ;-----------------------------------------------------------------------------
- process_full_path:
- mov bx,si
- dec bx ;BX points to last '\'
- mov di,bx
- common_stuff:
- call slashscan ;Set BX to last '\'
- ;Set DI to beginning of path
- ;Set SI to end of path
- call save_cur_dir
- call change_drive
- call change_dir ;Change to specified directory
- mov directory_set,1
- jmp loop1
-
- ;-----------------------------------------------------------------------------
- process_rel_path:
- cmp drive_set,0 ;Has the drive been set yet?
- jnz do_path_spec ;If it has, we must have a pathspec
- call checkdrive ;If not see if it is a drive..
- jmp loop1 ; and go back and loop through rest
- do_path_spec:
- mov di,si ;Set DI to beginning of relative path
- dec di
- xor bx,bx ;Set BX to 0, there is no last '\'
- jmp common_stuff ;Go do normal path processing
-
- error:
- mov dx,OFFSET nofoundswitch ;Print Illegal switch message
- call write_string
- mov dx,OFFSET illegalswitch ;Print Usage statement
- call write_string
- call send_crlf
- mov dl,16
- call goto_col
- mov dx,OFFSET legalswitches ;Print all legal switches
- call write_string
- call send_crlf
-
- mov ah,4ch ;Exit to DOS
- int 21h
-
- exit_check:
- cmp directory_set,0 ;Has the directory been set yet?
- jne exit_process_psp ;If yes, we can exit
-
-
- exit_default: ;If not
- call save_cur_dir ;Save the current directory
- mov cx,3 ;Move *.* to the filespec area
- mov si,OFFSET def_filespec
- call set_filespec
- cmp drive_set,0 ;Has the drive been set yet?
- je exit_process_psp ;If not, we can exit
- call change_drive ;If so, change to correct drive
- ; and exit
-
- exit_process_psp:
- pop bp ;Restore registers and leave
- pop si
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- ret
-
- process_psp ENDP
-
- public checkdrive
- ;-----------------------------------------------------------------------;
- ; This procedure checks if the 2 characters pointed to by DS:SI are a ;
- ; drive specification. If it is a legal drivespec the drive number ;
- ; will be put into tempdrive, and CL and SI are set as needed. ;
- ; If they are not legal, CL and SI are set back over these characters ;
- ; for further scanning. ;
- ;-----------------------------------------------------------------------;
- checkdrive PROC
-
- push ax
-
-
- dec si ;When alpha is found move back
- lodsw ; and get a whole word to test
- cmp ah,':' ;Do we have a drive specification?
- je setdrive ;If yes, go set it
- jmp exit_no
-
- setdrive:
- cmp al,'A' ;Check if under legal range
- jl exit_no
- cmp al,'z' ;Check if over legal range
- jg exit_no
- cmp al,'a' ;Check the case
- jl lowercase ;If less than 'a' it is lowercase
- sub al,'a'
- jmp ok
- lowercase:
- sub al,'A' ;Adjust from ASCII to drive number
- ok:
- dec cl
- mov tempdrive,al ;Store the drive number in memory
- jmp exit_checkdrive
- exit_no:
- inc cl
- sub si,2 ;Backup if no drive was selected
- exit_checkdrive:
- mov drive_set,1
- pop ax
- ret
-
- checkdrive ENDP
-
- public slashscan
- ;-----------------------------------------------------------------------;
- ; This procedure will scan a path specification and mark the end of it ;
- ; with a zero byte, and point SI to this zero byte, point BX to the ;
- ; backslash character. ;
- ;-----------------------------------------------------------------------;
- slashscan PROC
-
- loop2:
- jcxz exit_slashscan ;When count is zero, we're done
- dec cl ;Decrement count
- lodsb ;Get a byte
- cmp al,' ' ;If a space, path is complete
- je space_exit
- cmp al,0
- je space_exit
- cmp al,'\' ;This is what we are looking for!
- jne loop2
- mov bx,si
- dec bx ;Move BX to this '\'
- jmp loop2
-
- space_exit:
- inc cl ;Move back to the space
- dec si
- xchg si,bx ;End the patch with a ZERO
- xor al,al
- mov [bx],al
- xchg bx,si ;Move BX back to where it belongs
-
- exit_slashscan:
- ret
-
- slashscan ENDP
-
-
- public save_cur_dir
- ;-----------------------------------------------------------------------;
- ; This procedure gets the current directory and saves it in memory. ;
- ;-----------------------------------------------------------------------;
- save_cur_dir PROC
-
- push si
- mov si,OFFSET directory+1 ;Get OFFSET one past a '\'
- mov ah,47h
- mov dl,0
- int 21h ;Get current directory
- pop si
- ret
-
- save_cur_dir ENDP
-
-
- public change_drive
- ;-----------------------------------------------------------------------;
- ; This procedure changes to the drive number in tempdrive if necessary. ;
- ;-----------------------------------------------------------------------;
- change_drive PROC
-
- mov al,tempdrive
- cmp startdrive,al ;If a drive change was indicated
- je exit_change_drive ;call BIOS to change to it
- mov dl,tempdrive
- mov ah,0eh
- int 21h
- exit_change_drive:
- ret
-
- change_drive ENDP
-
-
- public change_dir
- ;-----------------------------------------------------------------------;
- ; This procedure tries to change to a specified directory. It assumes ;
- ; DI points to the beginning of a full path specification. BX points ;
- ; to the last '\' before the end. SI points to the byte after the last ;
- ; character in path specification. ;
- ;-----------------------------------------------------------------------;
- change_dir PROC
-
- push si
- push cx
- mov dx,di ;Assume whole thing is directory
- mov ah,3bh
- int 21h
- jnc default ;Is a legal directory
- cmp bx,0
- je pre_set_filespec
- xor ah,ah
- mov [bx],ah ;Separate filespec and path with a zero
- cmp di,bx ;Is the last '\' also the first '\'?
- je root_dir ;If so, we want to use just '\' as path
- mov ah,3bh ;Try this new directory
- int 21h
- jc error_change_dir ;Neither is legal directory
- jmp setfilespec
-
- root_dir:
- mov dx,OFFSET root ;Set for the '\' path
- mov ah,3bh ;Change to the '\' path
- int 21h
- jmp setfilespec
-
- default:
- mov cx,3
- mov si,OFFSET def_filespec ;Move *.* in as filespec
- call set_filespec
- jmp exit_change_dir
-
- pre_set_filespec:
- mov bx,di ;If BX was 0, we need to set it
- dec bx ;
- setfilespec:
- inc bx
- mov cx,si
- sub cx,bx
- mov si,bx ;DS:SI is source filespec
- call set_filespec
- jmp exit_change_dir
-
- error_change_dir:
- mov dx,OFFSET nofoundpath
- call write_string
- mov dx,OFFSET illegalswitch
- call write_string
- call send_crlf
-
- mov ah,4ch ;Return to DOS
- int 21h
-
-
- exit_change_dir:
- pop cx
- pop si
- mov bx,si
- mov al,20h
- mov [bx],al ;Move a space back over the ZERO
- ret
-
- change_dir ENDP
-
-
- public set_filespec
- ;-----------------------------------------------------------------------;
- ; This procedure will set the filespec to the desired pattern. ;
- ; On ENTRY: CX=number of characters to move, SI source for move. ;
- ;-----------------------------------------------------------------------;
- set_filespec PROC
-
- mov di,OFFSET filespec ;ES:DI is destination of filespec
- rep movsb ;Do the move
- ret
-
- set_filespec ENDP
-
-
- public write_date
- extrn write_decimal:proc, write_char:proc
- ;-----------------------------------------------------------------------;
- ; Prints a file's date when given the date stamp from the DTA ;
- ; ;
- ; Expects address of date to be DS:DX ;
- ;-----------------------------------------------------------------------;
- write_date proc
- push ax ;Save those registers!
- push bx
- push cx
- push dx
-
-
- mov bx,dx ;Move offset into BX
- mov ax,[bx] ;Move date into AX
- push ax ;Save it!
-
- and ax,01e0h ;Save only month bits(8-5)
- mov cl,5 ;Shift to get actual value in AX
- shr ax,cl
- cmp ax,9
- jg just_print1 ;If greater than 9 just print
- mov dl,'0' ;Otherwise, print a leading zero
- call write_char
- just_print1:
- mov dx,ax
- call write_decimal
- mov dl,'-'
- call write_char
-
- pop ax ;Get the correct date back
- push ax ;Save it again
- and ax,001fh ;Save only day bits (4-0)
- cmp ax,9
- jg just_print2 ;If greater than 9 just print
- mov dl,'0' ;Otherwise, add a leading zero
- call write_char
- just_print2:
- mov dx,ax
- call write_decimal
- mov dl,'-'
- call write_char
-
- pop ax ;Get back the date one more time
- and ax,0fe00h ;Save only the year bits (15-9)
- mov cl,9
- shr ax,cl ;Shift to get actual value
- add ax,80 ;Date is relative to 1980
- mov dx,ax
- call write_decimal
-
- pop dx
- pop cx
- pop bx
- pop ax
- ret
-
- write_date endp
-
-
- public write_time
- ;-----------------------------------------------------------------------;
- ; This procedure prints the time stamp associated with a file on the ;
- ; screen at the current cursor position. ;
- ; Expects DS:DX to be the date in the DTA. ;
- ;-----------------------------------------------------------------------;
- write_time PROC
- push ax ;Save registers of course
- push bx
- push cx
- push dx
-
- mov bx,dx
- mov ax,[bx] ;Get the time word into AX
- push ax ;Save the time for later
-
- and ax,0f800h ;Save only the hour bits(15-11)
- mov cl,11 ;Shift to get correct value is AX
- shr ax,cl
- mov bx,OFFSET time_table ;Get offset of date translation table
- xlat ;Get translated byte into AL
- mov bl,al ;Save AL for later use
- and bl,10h ;Save only AM/PM flag in BL
- mov cl,4 ;Shift for correct value in BL
- shr bl,cl
- test al,20h ;Test for the space bit
- jnz write_a_space ;If space bit on, write a space
- jmp continue ; otherwise, continue
- write_a_space:
- mov dl,' '
- call write_char
- continue:
- and al,0fh ;Now just save the hour number
- mov dx,ax ;Write the hour
- call write_decimal
- mov dl,':' ;Write time separator
- call write_char
-
- pop ax ;Get the date back
- and ax,07e0h ;Save only the minutes
- mov cl,5 ;Shift for correct value in AL
- shr ax,cl
- cmp ax,9 ;If min. > 9 no leading zero needed
- jg just_write
- mov dl,'0' ;Write the leading zero
- call write_char
- just_write:
- mov dx,ax
- call write_decimal ;Write the minutes
- mov al,bl ;Translate 0 into 'a' and 1 into 'p'
- mov bx,OFFSET am_pm_table
- xlat
- mov dl,al ;Write the 'a' or 'p'
- call write_char
-
-
- pop dx ;Restore registers and exit
- pop cx
- pop bx
- pop ax
- ret
-
- write_time ENDP
- public bin_to_ascii
- ;-----------------------------------------------------------------------;
- ; This procedure will take a 2 word (32 bit) number stored at DI:SI, ;
- ; where DI contains the most significant part and SI the least ;
- ; significant part, and convert it into a ASCII string and print it on ;
- ; the screen at the current cursor location. ;
- ;-----------------------------------------------------------------------;
- bin_to_ascii PROC
- push ax ;Save registers
- push bx
- push cx
- push dx
- push bp
- push si
- push di
-
- xor ax,ax ;Initialize to zero AX,BX,BP
- mov bx,ax
- mov bp,ax
- mov cx,32 ;32 bits to convert
- next_bit:
- shl si,1 ;Shift DI:SI left maintaining
- rcl di,1 ;the carry out
- xchg ax,bp ;Start work on BP
- call func4 ;Add to accumulator
- xchg ax,bp ;Put back BP
- xchg ax,bx ;Start work on BX
- call func4 ;Add to BX any carry caused by BP
- xchg ax,bx ;Put back BX
- call func4 ;Now do AX, adding any carry
- loop next_bit ;Continue for 32 bits
-
- ;-----------------------------------------------------------------------;
- ; At this point we have AX:BX:BP equal to the decimal number we want to ;
- ; print. AX=MSBs BP=LSBs ;
- ;-----------------------------------------------------------------------;
-
- cld ;Forward increments
- mov di,OFFSET p_field ;Destination is print field
- call form_reg ;Process AX digits
- mov ax,bx
- call form_reg ;Process BX digits
- mov ax,bp
- call form_reg ;Process CX digits
-
- mov bx,OFFSET p_field ;Now Remove excess digits and
- mov cx,14 ; commas.
- xor ax,ax
- form_loop:
- cmp BYTE PTR [bx],30h ;If a digit start printing here
- jg set_dx
- inc bx ;Try next char
- inc ax ;Increment counter of removed chars
- loop form_loop
- set_dx:
- sub ax,3 ;Calculate number of pad chars
- mov cx,ax ;Use this a loop amount
- spaces_add:
- mov dl,' ' ;Pad with spaces
- call write_char
- loop spaces_add
-
- mov dx,bx ;Print the comma'ed number
- call write_string
-
- pop di ;Restore registers
- pop si
- pop bp
- pop dx
- pop cx
- pop bx
- pop ax
-
- ret
- bin_to_ascii ENDP
-
- public form_reg
- ;-----------------------------------------------------------------------;
- ; This procedure will process the 4 BCD digits in the p_field to put ;
- ; commas in the number. It converts from BCD to ASCII. ;
- ;-----------------------------------------------------------------------;
- form_reg PROC
-
- push ax ;Save AX
- xchg al,ah ;Move the high bits to the low bits
- shr al,1 ;shift right 4 times
- shr al,1
- shr al,1
- shr al,1
- and al,0fh ;Convert to ASCII
- or al,030h
- cmp BytE PTR ES:[DI],',' ;If it is a comma skip it
- jne over1
- inc di
- over1:
- stosb ;Put char in print field
- pop ax ;Get back AX
- push ax ;Resave it
- xchg al,ah ;Move high bits to low bits
- and al,0fh ;Convert to ASCII
- or al,030h
- cmp BYTE PTR ES:[DI],',' ;Skip if comma
- jne over2
- inc di
- over2:
- stosb ;Store the byte in print field
- pop ax ;Get back AX
- mov ah,al ;Save low bits in high bits
- shr al,1 ;Shift low bits 4 times
- shr al,1
- shr al,1
- shr al,1
- and al,0fh ;Convert to ASCII
- or al,030h
- cmp BYTE PTR ES:[DI],',' ;Skip if comma
- jne over3
- inc di
- over3:
- stosb ;Store the byte
- xchg al,ah ;Get low bits back
- and al,0fh ;Convert to ASCII
- or al,030h
- cmp BYTE PTR ES:[DI],',' ;Skip if comma
- jne over4
- inc di
- over4:
- stosb ;Store in print field
-
- ret ;Return!
-
- form_reg ENDP
-
- ;-----------------------------------------------------------------------;
- ; This procedure takes a 2 byte value and accumulates a BCD value in ;
- ; it, taking into account the carry from the last operation whether it ;
- ; be a shift or a ADC. On exit there may also be a carry active for ;
- ; use in the next 2 byte register. Entry is in AX. ;
- ;-----------------------------------------------------------------------;
-
- func4 PROC
- adc al,al ;Mult by 2 and add carry
- daa ;Adjust to BCD
- xchg al,ah ;Now work on other digit
-
- adc al,al ;Mult by 2 and add carry
- daa ;Adjust to BCD
- xchg al,ah ;Return AX to correct position
- ret
- func4 ENDP
-
- public write_volume
- ;-----------------------------------------------------------------------;
- ; This procedure will write out a volume name message for the current ;
- ; drive. ;
- ;-----------------------------------------------------------------------;
- write_volume PROC
- mov ah,2fh
- int 21h ;Get the current DTA
-
- mov dx,OFFSET volumespec ;Get the *.* filespec
- mov cx,08h ;8 is volume attrib.
- mov ah,4eh ;Find file
- int 21h
- jnc no_carry
- jmp carry_set
- no_carry:
- xor cx,cx
- carry_set:
- mov dx,OFFSET volumemess1 ;"Volume in Drive "
- call write_string
- mov dl,tempdrive ;Get specified drive
- add dl,'A' ;Adjust to ASCII
- call write_char
- cmp cx,0
- jnz no_volume
- mov dx,OFFSET volumemess2 ;" is "
- call write_string
-
- mov dx,OFFSET FName ;Get offset of volume name
- mov bx,dx ;Put in BX for addressing
- jmp next_byte
-
- no_volume:
- mov dx,OFFSET volumemess3 ;" has no label. "
- jmp done_no_ext
-
-
- next_byte:
- xor al,al ;Clear for compare
- cmp al,[bx] ;If we see a zero, were are done
- je done_no_ext
- mov ax,'.' ;Now see if it is a '.'
- cmp al,[bx]
- je squish ;If so, then take the '.' out
- inc bx ;Otherwise, try next character
- jmp next_byte
- squish:
- mov ah,[bx+1] ;Move 4 bytes to a position
- mov al,[bx+2] ;One less than their previous
- mov ch,[bx+3] ;positions
- mov cl,[bx+4]
- mov [bx],ah
- mov [bx+1],al
- mov [bx+2],ch
- mov [bx+3],cl
- done_no_ext:
- call write_string ;Write the volume name
- call send_crlf
- mov dx,OFFSET dirmess1 ;"Directory of "
- call write_string
- mov dl,tempdrive ;Put the drive letter in front SS
- add dl,'A' ; of the path listing of dir SS
- call write_char ;Puts colon after drive letter SS
- mov dx,OFFSET colon ; SS
- call write_string ; SS
- mov dx,OFFSET tempdir ;Write the specified directory
- call write_string
- mov dx,OFFSET dirmess2 ;" Filespec: "
- call write_string
- mov dx,OFFSET filespec ;Write current file specification
- call write_string
- call send_crlf
- ret
- write_volume ENDP
-
- public write_trailer
- EXTRN goto_col:proc
- ;-----------------------------------------------------------------------;
- ; This will print the number of files specified, byte count in these ;
- ; files and bytes left on current drive. ;
- ;-----------------------------------------------------------------------;
- write_trailer PROC
- cmp wide_flag,0
- jne wide_entry
- mov si,WORD PTR accum_filesize
- mov di,WORD PTR accum_filesize[2]
- call bin_to_ascii
- mov dx,OFFSET trailermess0
- call write_string
- wide_entry:
- mov dx,files ;Write number of files
- call write_decimal
- mov dx,OFFSET trailermess1 ;Write "File(s) "
- call write_string
- mov dl,0 ;Set for current drive
- mov ah,36h ;Get free clusters
- int 21h
- xor dx,dx
- mul cx ;Calculate free bytes
- mul bx
- mov si,ax ;Write the ASCII number
- mov di,dx
- call bin_to_ascii
- mov dx,OFFSET trailermess2 ;Write " bytes free. "
- call write_string
- ret
- write_trailer ENDP
-
- public write_attributes
- ;-----------------------------------------------------------------------;
- ; This procedure will print the attribute of each file as it is listed ;
- ; in the directory. DS:DX should point to the Attrib section in DTA. ;
- ;-----------------------------------------------------------------------;
- write_attributes PROC
- push ax
- push bx
- push dx
-
- mov bx,dx ;Move offset into BX
- mov ax,[bx] ;Get attribute into AX
-
- test ax,0001h ;Is the file read only?
- jnz write_R
- mov dl,'.' ;If not write a DOT
- call write_char
- R_return:
- test ax,0002h ;Is the file hidden?
- jnz write_H
- mov dl,'.'
- call write_char
- H_return:
- test ax,0004h ;Is the file a system file?
- jnz write_S
- mov dl,'.'
- call write_char
- S_return:
- test ax,0010h ;Is the file a directory?
- jnz write_D
- mov dl,'.'
- call write_char
- D_return:
- test ax,0020h ;Is the file an archive file?
- jnz write_A
- mov dl,'.'
- call write_char
- jmp done_write_attributes
-
- write_R:
- mov dl,'R' ;Write the characters
- call write_char
- jmp R_return
- write_H:
- mov dl,'H'
- call write_char
- jmp H_return
- write_S:
- mov dl,'S'
- call write_char
- jmp S_return
- write_D:
- mov dl,'D'
- call write_char
- jmp D_return
- write_A:
- mov dl,'A'
- call write_char
-
- done_write_attributes:
- pop dx ;Restore the registers and return
- pop bx
- pop ax
- ret
-
- write_attributes ENDP
-
- public tally_files
- ;-----------------------------------------------------------------------;
- ; This procedure adds the 32bit number currently in DI:SI ;
- ; to the 32bit number in accum_filesize. ;
- ;-----------------------------------------------------------------------;
- tally_files PROC
- push ax
- push dx
- push di
-
- mov ax,WORD PTR accum_filesize ;Add least significant bytes
- add ax,si
- mov dx,WORD PTR accum_filesize[2] ;Add most significant bytes
- adc dx,di ; with carry
- cld
- mov di,OFFSET accum_filesize ;Store the result in memory
- stosw
- mov ax,dx
- stosw
-
- pop di
- pop dx
- pop ax
- ret
- tally_files ENDP
-
-
- END disk_dir