SDL.ASM  ·  ASM  ·  31.6 KB  ·  1984-08-05  ·  from IBM-PC-User-Group-Software-Library_Disk-44_Feb-1980
    TITLE   SD - SORTED DIRECTORY V3.0
    PAGE    64,132                                         ; 3/24/84
COMMENT |
    SD [d:][filename[.ext]] [options]
     [filespec] same as for DIR command
 
     [options] * /A - List hidden files.
               * /E - Without screen erase.
               * /W - Don't wait when screen full.                  djm
               * /R - Include directory entries (high intensity)    djm
               * /M - Display Modified entries only                 djm
                 /X - Sort by extension.
                 /S - Sort by size.
                 /D - Sort by date/time.
                 /N - Do not sort, original order.
                 /H - Help - only display options                   djm
 
       Default = *.* sorted by name.ext with screen erase.
       * - Option may be combined with other options.
 
   This source file was created from an object file obtained
 from Gene Plantz's BBS in Chicago. The original file name
 was SD.HEX.  I then used DEBUG and CAPTURE to get the first
 dis-assembly which  was then edited with WORDSTAR to create
 a source that when assembled using MASM would duplicate the
 original object file.
   Comments have been added and I do hope they are helpful.
 I have made several modifications to the first version and
 am continuing to add comments.  This source file is an
 excellent example for anyone wishing to learn 8086/8088
 assembly language.  Use at your own risk and feel free to
 share this file with your friends.
   I certainly wish that John Chapman would publish his
 source file.  His comments are sure to be more meaningful
 than mine could ever be.  Some of the conversion routines
 are very elegant, but difficult to understand.  As far as
 I'm concerned, PRINTDD is magic.
   Several modifications have been made.  They are:
 
        1. Filespecs are processed like DIR does.
        2. No sort option was added. /N
        3. Pause when screen full option added. /P  changed to /W by DJM
    4. Number of files found is printed.
 
                                    Ted Reuss
                                    Houston, TX
 
    SDIR Version 2.2  The GETFREE Subroutine was updated for DOS 2.0
    April 1, 1983   by   Jack Y. Fong
    Changes are denoted by "JYF" at the end of changed lines.

    I (Dave Mc Laughlin) have also made several modifications: (V 3.0)
        Pause is now standard unless /P is entered to defeat
        Color is now supported on color monitors
        Free space is now reported at the bottom, along with
          directory total (to give an idea of how many diskettes
          may be required for backup)
        Volume and current directory are shown on the top line
          (my apologies to Capitol PC Club for removing their logo)
        Modified files are shown with a + sign in place of the .
        The /R option (show sub directory names) has been added
        The /P option was changed to /W(ait) and /M (modified only) added

    NOTE:  THIS MODIFIED VERSION REQUIRES DOS 2.0 AND ANSI.SYS TO
           BE INSTALLED - SEE DOS REFERENCE MANUAL PAGE 13-2

|
 
    SUBTTL  EQUATES & STRUCTURES
    PAGE
IF1
DOSCALL MACRO       FUNC,PARM1
.xcref
F_C =       FUNC
IFNB <PARM1>
IF F_C EQ 2 OR (F_C GE 4 AND F_C LE 6) OR F_C EQ 14 OR F_C EQ 46
    MOV     DL,PARM1
ELSE
    MOV     DX,OFFSET PARM1
ENDIF
ENDIF
        MOV     AH,FUNC
        INT     21H
.cref
        ENDM
ENDIF
.SALL   ;supress all macro expansions
;       PC-DOS INTERRUPT 21H FUNCTION CODES
;
@CHROUT EQU     2       ;display char in DL
@KEYIN  EQU     8       ;kybd input w/o echo
@STROUT EQU     9       ;print string terminated with $
@CKEYIN EQU     12      ;clr kybd bufr & do inp.func in AL
@SRCH1  EQU     17      ;search for first dir entry
@SRCH2  EQU     18      ;search for next dir entry
@GETDSK EQU     25      ;get default disk drive
@SETDTA EQU     26      ;set disk transfer addr
@FATAD2 EQU     28      ;get FAT of drive # in DL
@PARSEF EQU     41      ;parse filename
@GETDTE EQU     42      ;get system date
@GETTME EQU     44      ;get system time
@DSKFSP EQU     36H     ;get disk free space                            JYF
@GETVER EQU     30H     ;get version number                             JYF
@GETDIR EQU     47H     ;get directory                                  djm
 
CR      EQU     0DH     ;carriage return
LF      EQU     0AH     ;line feed
FCB_1   EQU     5CH     ;fcb for parameter 1
PARAM_L EQU     80H     ;# characters in PARAM_B
PARAM_B EQU     81H     ;DOS cmd parameter buffer.
 
; PC-DOS packed date   <yyyyyyym mmmddddd>
P_DTE           RECORD  P_YR:7,P_MO:4,P_DY:5
; PC-DOS packed time   <hhhhhmmm mmmsssss>
P_TME           RECORD  P_HR:5,P_MI:6,P_2S:5
 
DIRNTRY STRUC               ;directory entry structure
LNK     DW      0       ;ptr to next entry
NAM     DB      8 DUP(0),'.' ;filename
EXT     DB      3 DUP(0) ;extension
TME     DW      0       ;time
DTE     DW      0       ;date
SZL     DW      0       ;low word of size
SZH     DW      0       ;high word of size
DIRNTRY ENDS
 
        SUBTTL  DATA AREA & INITIALIZATION
        PAGE
SDIR    SEGMENT PUBLIC 'CODE'
        ASSUME  CS:SDIR,DS:SDIR,ES:SDIR
        ORG     100H
MAIN    PROC    FAR
        JMP     STARTS

DIRWRK  DB      64 DUP (' ') ;directory work area                   djm

SCRCOL  DB      27,'[33;44m$' ; brown on blue                       djm
CLS     DB      27,'[2J$'       ;clear screen seq for 2.0           djm
ROOT    DB      '* * ROOT * *',8 DUP (' ') ;                        djm
HI_INT  DB      27,'[1m$'       ;high intensity for dir entry       djm
BROWN   DB      27,'[0;33;44m$' ;return to brown foreground         djm
DIRSW   DB      0       ;0=this is not a directory entry            djm
TOTL    DW      0       ;low order word of total size used          djm
TOTH    DW      0       ;high order                                 djm


DIRLNK  DW      DIRBUF  ;ptr to next opening in DIRBUF
C1LNK   DW      0       ;ptr to row 1, column 1
C2LNK   DW      0       ;ptr to row 1, column 2
NBRFILS DW      0       ;# of files or detail lines
SRTFLG  DB      0       ;if = 0 then sort else no sort
CLSFLG  DB      0       ;if = 0 then clear screen
EXTFLG  DB      0       ;if <> 0 then sort by ext
SIZFLG  DB      0       ;if <> 0 then sort by size
DTEFLG  DB      0       ;if <> 0 then sort by date/time
PSEFLG  DB      'W'     ;if <> 0 then pause if screen full          djm
MODFLG  DB      0       ;if <> 0 then display modified only         djm
OPTFLG  DB      0       ;if <> 0 then display options (no directory)djm
LPERSCR EQU 25      ;Lines per screen
LINCNT  DB      LPERSCR-4 ;Number of lines left
PSEMSG  DB      27,'[32mStrike a key when ready . . . ' ;           djm
        DB      27,'[33m$'      ;return color to brown              djm
 
HDNG1   DB      'Vol: ',27,'[31;43m'    ;red on brown background    djm
VOLLOC  DB      11 DUP (' ')    ;put volume label here              djm
        DB      27,'[33;44m  '  ;set color back to normal           djm
        DB      'Dir: ',27,'[31;43m'     ;red on brown background   djm
DIRLOC  DB      17 DUP (' ')    ;put directory name here            djm
        DB      27,'[33;44m  '  ;set color back to normal           djm
        DB      'Drive: '
        DB      27,'[31;43m'    ;red on brown                       djm
HDRVE   DB      '@'             ;drive goes here                    djm
        DB      27,'[33;44m'    ;set color back to normal           djm
        DB      3 DUP (' '),'Date: '    ;                           djm
        DB      27,'[31;43m'    ;red on brown                       djm
D_MM    DW      '00'            ;Month
        DB      '/'
D_DD    DW      '00'            ;Day
        DB      '/'
D_YY    DW      '00'            ;Year
        DB      27,'[33;44m '   ;color back to normal               djm
        DB      'Time: '
        DB      27,'[31;43m'    ;red on brown                       djm
T_HH    DW      '00'            ;Hours
        DB      ':'
T_MM    DW      '00'            ;Minutes
        DB      27,'[33;44m'    ;back to normal                     djm
        DB      CR,LF
CRLF    DB      CR,LF,'$'
HDNG2   DB      'Filespec.ext  Bytes-  --Last Change--$'
        DB      8 DUP(' ')
SPACES  DB      '$'
RED     DB      27,'[31m',CR,LF,'$'     ;                           djm
HDNG3   DB      ' File(s)',8 DUP (' '),'$'
HDNG5   DB      ' Directory Total',9 DUP (' '),'$'      ;           djm
HDNG6   DB      ' Free Space'
        DB      27,'[0;33;44m',CR,LF,'$' ;reset colors              djm

OPTHDG  DB      27,'[1;25H',27,'[31;43m'        ;option headings   ;djm
        DB      'S O R T E D   D I R E C T O R Y'                  ;djm
        DB      27,'[33;44m'                                       ;djm
        DB      27,'[3;10HDisplay Options:'                        ;djm
        DB      27,'[5;15H/A     Include hidden files'             ;djm
        DB      27,'[6;15H/R     Include directory names'          ;djm
        DB      27,'[7;15H/M     Show only files that have been '  ;djm
        DB      'modified since last backup'                       ;djm
        DB      27,'[8;15H/E     Don',39,'t erase screen before display'
        DB      27,'[9;15H/W     Don',39,'t wait when screen is full'
        DB      27,'[13;10HSort Options:'                          ;djm
        DB      27,'[15;15H/X     Sort by EXTENSION'               ;djm
        DB      27,'[16;15H/S     Sort by SIZE'                    ;djm
        DB      27,'[17;15H/D     Sort by DATE and time'           ;djm
        DB      27,'[18;15H/N     No sort'                         ;djm
        DB      27,'[20;1H$'                                       ;djm
        SUBTTL  DISK TRANSFER AREA & FREE SPACE ENTRY DEFS
        PAGE
 
XFCB    DB      -1,7 DUP(0),11 DUP('?'),25 DUP(0)
ATTRIB  EQU     XFCB+6          ;file attribute
DRVNBR  EQU     ATTRIB+1        ;drive # (1=A, 2=B, etc.)
 
DTA     DB      40 DUP(0)       ;Disk Transfer Area used
FILNAME EQU     DTA+8           ;by SRCHDIR for the
FILTIME EQU     DTA+30          ;directory search.
FILSIZE EQU     DTA+36
FILATR  EQU     DTA+19
 
FREESPC DW      0               ;Free space entry.
        DB      '*FREE SPACE*',4 DUP(0)
LOSIZE  DW      0               ;of free space
HISIZE  DW      0               ;of free space
 
        SUBTTL  MAIN PROGRAM SECTION
        PAGE
STARTS:
        PUSH    DS              ;Set up the
        XOR     AX,AX           ; stack for a
        PUSH    AX              ; return to DOS.
        CALL    GETARGS         ;Process arguments
        CALL    SRCHDIR         ;Search directory
        CMP     SRTFLG,0        ;Check if any sort
        JZ      A1              ; option selected.
        CALL    LNKDIRB         ;Leave in original
        JMP     SHORT A2        ; directory order.
A1:     CALL    SRTDIRB         ;Sort by major key
A2:     MOV     AL,OPTFLG       ;See if only options wanted         djm
        OR      AL,AL           ;See if H request for help          djm
        JZ      A3              ;Wasn't                             djm
        CALL    SHOWOPT         ;Show option screen                 djm
        JMP     SHORT A99       ;get out                            djm
A3:     CALL    GETFREE         ;Get free space
        CALL    SPLTLST         ;Set up for 2 columns
        CALL    PRTHDNG         ;Print headings
        CALL    PRTDRVR         ;Print detail lines
        CALL    PRTNFLS         ;Print # of files
A99:    RET                     ;Return to DOS
MAIN    ENDP
 
        SUBTTL  SHOWOPT - SHOW OPTIONS
SHOWOPT PROC    NEAR            ;                                    djm
        DOSCALL @STROUT,CLS     ;clear the screen                    djm
        DOSCALL @STROUT,SCRCOL  ;make screen colorful                djm
        DOSCALL @STROUT,OPTHDG  ;display options                     djm
        RET
SHOWOPT ENDP

        SUBTTL  GETARGS - PROCESS ARGUMENTS
        PAGE
GETARGS PROC    NEAR
        MOV     SI,PARAM_B      ;point to cmd buffer
        MOV     DI,OFFSET DRVNBR ;point to FCB
        MOV     AL, 1111B       ;Select parse options
        DOSCALL @PARSEF         ;Parse filename
        CMP     BYTE PTR [DI],0 ;If <> 0 then
        JNZ     B1              ; not default drive
        DOSCALL @GETDSK         ;AL <- default disk
        INC     AL              ;Increment drive #
        STOSB                   ;Save drive #
B1:     MOV     SI,PARAM_L      ;SI <- ptr cmd length
        MOV     CH,0
        MOV     CL,[SI]         ;CL <- # chars in cmd
        JCXZ    B99             ;                                   djm
B2:     INC     SI              ;Point to next char
        CMP     BYTE PTR [SI],'/'
        JNZ     B8              ;If not a slash
        MOV     AL,[SI+1]       ;AL <- option letter
        AND     AL,0DFH         ;Force to upper-case
        CMP     AL,'A'          ;Hidden & system files?
        JNZ     B31             ;Nope, try next one.                djm
        OR      BYTE PTR ATTRIB,2+4  ;Hidden & system               djm
B31:    CMP     AL,'R'          ;directory entries?                 djm
        JNZ     B3              ;Nope, try next one.                djm
        OR      BYTE PTR ATTRIB,10H     ;Directory                  djm
B3:     CMP     AL,'E'          ;Without screen erase?
        JNZ     B4              ;Nope, try next one.
        MOV     CLSFLG,AL
B4:     CMP     AL,'S'          ;Sort by size?
        JNZ     B5              ;Nope, try next one.
        MOV     SIZFLG,AL
B5:     CMP     AL,'D'          ;Sort by date/time?
        JNZ     B6              ;Nope, try next one.
        MOV     DTEFLG,AL
B6:     CMP     AL,'X'          ;Sort by extension?
        JNZ     B7              ;Nope, try next one.
        MOV     EXTFLG,AL
B7:     CMP     AL,'N'          ;Original order?
        JNZ     B8              ;Nope, try next one.
        MOV     SRTFLG,AL
B8:     CMP     AL,'W'          ;Wait when screen full?
        JNZ     B9              ;Nope, try next one.
        MOV     AL,0            ;put zero in al                     djm
        MOV     PSEFLG,AL       ;                                   djm
B9:     CMP     AL,'M'          ;Just show modified entries?        djm
        JNZ     B10             ;Nope, try next one.                djm
        MOV     MODFLG,AL       ;                                   djm
B10:    CMP     AL,'H'          ;Just show options?                 djm
        JNZ     B11             ;Nope, try next one                 djm
        MOV     OPTFLG,AL       ;                                   djm
B11:    LOOP    B2              ;Test for another param.
B99:    RET
GETARGS ENDP
 
        SUBTTL  SRCHDIR - SEARCH DIRECTORY
        PAGE
SRCHDIR PROC    NEAR
        MOV     BH,ATTRIB ;save attrib                              djm
        MOV     BYTE PTR ATTRIB,8       ;get volume label           djm
        DOSCALL @SETDTA,DTA                                         djm
        DOSCALL @SRCH1,XFCB     ;get volume label                   djm
        OR      AL,AL           ;found it?                          djm
        JNZ     C11             ;none found                         djm
        MOV     SI,OFFSET FILNAME ;source field                     djm
        MOV     DI,OFFSET VOLLOC        ;put in vol label           djm
        MOV     CX,11           ;length                             djm
        CLD                     ;clear direction flag               djm
        REPZ    MOVSB           ;do it                              djm
C11:    MOV     ATTRIB,BH       ;restore attribute                  djm
        DOSCALL @SETDTA,DTA     ;Set DTA for dir. search
        DOSCALL @SRCH1,XFCB     ;First call to search dir.
C1:     OR      AL,AL
        JZ      C21             ;found                              djm
        JMP     C2              ;not found - quit looking           djm
C21:    MOV     BX,DIRLNK       ;BX <- base of DIRBUF
        LEA     DI,[BX].NAM
        MOV     SI,OFFSET FILNAME
        MOV     AL,[SI]         ;get first byte of entry            djm
        CMP     AL,'.'          ;see if sub directory entry         djm
        JZ      C41             ;yes - skip                         djm
        MOV     CX,SIZE NAM
        CLD
        REPZ    MOVSB           ;Move filename to DIRBUF
        MOV     AL,FILATR       ;load file attributes               djm
        TEST    AL,20h          ;see if attr bit set                djm
        JZ      C3              ;no                                 djm
        MOV     BYTE PTR [DI],'+'       ;                           djm
        JMP     SHORT C4        ;                                   djm
C3:     ; not modified - now see if /M set                          djm
        CMP     MODFLG,0        ;see if /M set                      djm
        JNE     C41             ;wasn't                             djm
        TEST    AL,10H          ;see if directory entry             djm
        JZ      C31             ;no                                 djm
        MOV     BYTE PTR [DI],'-'       ;store a minus for dir      djm
        JMP     SHORT C4        ;                                   djm
C31:    MOV     BYTE PTR [DI],'.' ; Store a period
C4:     INC     DI
        MOV     CX,SIZE EXT
        REPZ    MOVSB           ;Move ext to DIRBUF
        MOV     SI,OFFSET FILTIME
        MOVSW                   ;Move time to DIRBUF
        MOVSW                   ;Move date to DIRBUF
        MOV     SI,OFFSET FILSIZE
        MOV     AX,[SI]         ;get number for size addition       djm
        ADD     TOTL,AX         ;add                                djm
        MOVSW                   ;Move size to DIRBUF
        MOV     AX,[SI]         ;get high order                     djm
        ADC     TOTH,AX         ;add                                djm
        MOVSW
        ADD     BX,SIZE DIRNTRY ;Point to next entry
        MOV     DIRLNK,BX       ;Save ptr
        INC     NBRFILS         ;Increment file count
C41:    DOSCALL @SRCH2,XFCB     ;Search for next file
        JMP     C1              ;Loop for next one
C2:     RET
SRCHDIR ENDP
 
        SUBTTL  SRTDIRB - SORTS ENTRIES IN DIRBUF
        PAGE
SRTDIRB PROC    NEAR    ;Sorts directory entries in DIRBUF
        MOV     DI,OFFSET DIRBUF ;Point to DIRBUF
D1:     CMP     DI,DIRLNK       ;Are there anymore?
        JNC     D8              ;NO, exit
        MOV     SI,OFFSET C1LNK ;Start with column 1 ptr
D2:     MOV     BX,SI
        MOV     SI,[BX]         ;SI<-ptr to next entry
        OR      SI,SI
        JZ      D7              ;if link=0
        MOV     AX,SI
        MOV     DX,DI
        XOR     CL,CL           ;CL <- 0
        CMP     CL,SIZFLG
        JNZ     D5              ;If sort by size
        CMP     CL,DTEFLG
        JNZ     D4              ;If sort by date/time
        CMP     CL,EXTFLG
        JNZ     D3              ;If sort by ext
        LEA     SI,[SI].NAM
        LEA     DI,[DI].NAM
        MOV     CX,1+SIZE NAM+SIZE EXT  ;# of bytes
        JMP     SHORT D6
D3:     LEA     SI,[SI].EXT     ;Sort by extension
        LEA     DI,[DI].EXT
        MOV     CX,SIZE EXT     ;# of bytes
        JMP     SHORT D6
D4:     LEA     SI,[SI].DTE     ;Sort by date/time
        LEA     DI,[DI].DTE
        MOV     CX,2            ;# of words
        STD
        REPZ    CMPSW
        MOV     DI,DX
        MOV     SI,AX
        JBE     D2
        JMP     SHORT D7
D5:     LEA     SI,[SI].SZH     ;Sort by size
        LEA     DI,[DI].SZH
        MOV     CX,2            ;# of words
        STD
        REPZ    CMPSW
        MOV     DI,DX
        MOV     SI,AX
        JBE     D2
        JMP     SHORT D7
D6:     CLD                     ;Sort by name.ext
        REPZ    CMPSB
        MOV     DI,DX
        MOV     SI,AX
        JBE     D2
D7:     MOV     [DI],SI
        MOV     [BX],DI
        ADD     DI,SIZE DIRNTRY ;Point to next entry
        JMP     D1
D8:     RET
SRTDIRB ENDP
 
        SUBTTL
        PAGE
; LNKDIRB - LINKS ENTRIES IN DIRBUF
 
LNKDIRB PROC    NEAR            ;LINK ENTRIES IN DIRBUF
        MOV     DI,OFFSET DIRBUF
        MOV     C1LNK,DI       ;Point to 1st entry
        MOV     CX,NBRFILS      ;Set loop counter
        DEC     CX
LNK1:   MOV     BX,DI
        ADD     DI,SIZE DIRNTRY ;Offset to next entry
        MOV     [BX],DI         ;Store ptr
        LOOP    LNK1            ;Link next entry
        MOV     [DI],CX         ;Last ptr <- null
        RET
LNKDIRB ENDP
 
; SPLTLST - SPLITS LINKED LIST IN HALF
 
SPLTLST PROC    NEAR
        MOV     CX,NBRFILS      ;Get # of entries
        SAR     CX,1            ; and divide by 2
        JZ      F2              ;if NBRFILS < 2
        ADC     CL,0            ;Account for odd #
        MOV     BX,OFFSET C1LNK
F1:     MOV     BX,[BX]         ;Chain thru list to
        LOOP    F1              ; last row of column 1.
        MOV     AX,[BX]         ;Get ptr to 1st row of col 2
        MOV     C2LNK,AX        ; C2LNK <- R1,C2 ptr
        MOV     [BX],CX         ;Last row of col 1 <- null
F2:     RET
SPLTLST ENDP
 
        SUBTTL  GETFREE - GET DISK FREE SPACE
GETFREE PROC    NEAR            ;cluster = allocation unit
        MOV     DL,DRVNBR       ;Get drive #
        PUSH    DS              ;Save DS
        DOSCALL @DSKFSP         ;get disk free space                JYF
        MUL     BX              ;AX (sectors/clustor) * BX (free cluJYF
        MOV     DX,AX           ;                                   JYF
        MUL     CX              ;AX * CX (bytes/clustor)            JYF
E5:                             ;                                   JYF
        POP     DS              ;Restore DS
        MOV     LOSIZE,AX       ;Save the 32 bit
        MOV     HISIZE,DX       ; binary free space
        RET
GETFREE ENDP
 
        SUBTTL  PRTHDNG - PRINT HEADINGS
        PAGE
PRTHDNG PROC        NEAR
        MOV     AL,CLSFLG
        OR      AL,AL
        JNZ     G1              ;If not erase screen
        DOSCALL @STROUT,CLS     ;clear screen for 2.0               djm
G1:     MOV     AL,DRVNBR       ;Get drive #
        ADD     HDRVE,AL        ;Convert to ascii
        DOSCALL @GETDTE ; CX<-year, DH<-month, DL<-day
        MOV     AL,DH
        AAM
        XCHG    AL,AH
        OR      D_MM,AX         ;Fold into month
        MOV     AL,DL
        AAM
        XCHG    AL,AH
        OR      D_DD,AX         ;Fold into day
        MOV     AX,CX
        SUB     AX,1900
        AAM
        XCHG    AL,AH
        OR      D_YY,AX         ;Fold into year
        DOSCALL @GETTME ; CH<-hours, CL<-minutes
        MOV     AL,CH           ;AL<-binary hours
        AAM                     ;Convert AL to two
        XCHG    AL,AH           ; BCD digits in AX.
        OR      T_HH,AX         ;Fold into hours
        MOV     AL,CL           ;AL<-binary minutes
        AAM                     ;Convert AL to two
        XCHG    AL,AH           ; BCD digits in AX.
        OR      T_MM,AX         ;Fold into minutes
        DOSCALL @STROUT,SCRCOL  ;make screen colorful               djm
        MOV     DL,DRVNBR       ;set dl to current drive            djm
        MOV     SI,OFFSET DIRWRK ;point to work area                djm
        DOSCALL @GETDIR         ;get directory                      djm
        MOV     AL,[SI]         ;get 1st char                       djm
        CMP     AL,0            ;see if no directory name           djm
        JNE     G11             ;this is root directory             djm
        MOV     SI,OFFSET ROOT  ;get * * ROOT * *                   djm
G11:    MOV     DI,OFFSET DIRLOC  ;                                 djm
        CLD                     ;clear direction flag               djm
        MOV     CX,17           ;                                   djm
        REPZ    MOVSB           ;                                   djm
        DOSCALL @STROUT,HDNG1   ;Print main heading
        DOSCALL @STROUT,HDNG2   ;Print column 1 heading
        CMP     WORD PTR C2LNK,0
        JZ      G2              ;If not 2 columns
        DOSCALL @STROUT,SPACES-5 ;Print 5 spaces
        DOSCALL @STROUT,HDNG2   ;Print column 2 heading
G2:     DOSCALL @STROUT,CRLF    ;Start a new line
        RET
PRTHDNG ENDP
 
        SUBTTL  PRINT DETAIL LINES
        PAGE
PRTDRVR PROC    NEAR            ;Driver routine
        MOV     BX,C1LNK
        OR      BX,BX           ;more to print?
        JZ      H2              ; no, return
        MOV     AX,[BX]
        MOV     C1LNK,AX
        CALL    PRTDTL          ;print column one
        MOV     BX,C2LNK
        OR      BX,BX
        JZ      H1              ;If no column 2 entry
        DOSCALL @STROUT,SPACES-5 ;print 5 spaces
        MOV     AX,[BX]
        MOV     C2LNK,AX
        CALL    PRTDTL          ;print column two
H1:     DOSCALL @STROUT,CRLF
        CMP     PSEFLG,0        ;Check for pause option
        JZ      PRTDRVR         ;Nope, continue
        DEC     LINCNT          ;Decrement line counter
        JNZ     PRTDRVR         ;If page not full?
        MOV     LINCNT,LPERSCR-2 ;Reset to # lines/screen
        DOSCALL @STROUT,PSEMSG  ;Display pause message.
        MOV     AL,@KEYIN       ;Specify input function
        DOSCALL @CKEYIN         ;Wait for key press
        DOSCALL @STROUT,CRLF    ;Set to new line
        JMP     PRTDRVR         ;Go do the next line
H2:     RET
PRTDRVR ENDP
 
PRTDTL  PROC    NEAR    ;Prints file.ext, size, date & time
        MOV     AL,[BX][0AH]    ;get file.ext separator             djm
        CMP     AL,'-'          ;see if minus inserted              djm
        JNZ     SHORT I0        ;not a Dir entry                    djm
        MOV     BYTE PTR [BX][0AH],' '  ;clear minus sign           djm
        DOSCALL @STROUT,HI_INT  ;set next chars to high intensity   djm
        OR      DIRSW,1         ;set switch on                      djm
I0:     MOV     CX,1+SIZE NAM+SIZE EXT
        SUB     DI,DI           ;DI <- 0
I1:     DOSCALL @CHROUT,[BX+DI].NAM
        INC     DI              ;point to next char.
        LOOP    I1              ;go do next char.
        CMP     DIRSW,1         ;see if this is directory entry     djm
        JNZ     I11             ;no                                 djm
        DOSCALL @STROUT,SPACES-8 ;print 8 spaces instead of size    djm
        JMP     SHORT I12
I11:    PUSH    BX              ;save entry base
        MOV     SI,[BX].SZL     ;SI <- low size
        MOV     DI,[BX].SZH     ;DI <- high size
        CALL    PRINTDD         ;Print size
        POP     BX              ;restore entry base
I12:    DOSCALL @STROUT,SPACES-2 ;print 2 spaces
        MOV     AX,[BX].DTE     ;AX <- packed date
        CALL    PRTDTE
        DOSCALL @STROUT,SPACES-2 ;print 2 spaces
        MOV     AX,[BX].TME     ;AX <- packed time
        CALL    PRTTME
        CMP     DIRSW,1         ;see if switch on                   djm
        JNZ     I2              ;no                                 djm
        MOV     DIRSW,0         ;shut off switch                    djm
        DOSCALL @STROUT,BROWN   ;put back screen color              djm
I2:     RET
PRTDTL  ENDP
 
        SUBTTL  PRINTDD - PRINT A DOUBLE WORD IN DI:SI
        PAGE
PRINTDD PROC    NEAR    ;Prints a 32 bit integer in DI:SI
        XOR     AX,AX           ;Zero out the
        MOV     BX,AX           ; working
        MOV     BP,AX           ; registers.
        MOV     CX,32           ;# bits of precision
J1:     SHL     SI,1
        RCL     DI,1
        XCHG    BP,AX
        CALL    J6
        XCHG    BP,AX
        XCHG    BX,AX
        CALL    J6
        XCHG    BX,AX
        ADC     AL,0
        LOOP    J1
        MOV     CX,1710H        ;5904 ?
        MOV     AX,BX
        CALL    J2
        MOV     AX,BP
J2:     PUSH    AX
        MOV     DL,AH
        CALL    J3
        POP     DX
J3:     MOV     DH,DL
        SHR     DL,1            ;Move high
        SHR     DL,1            ; nibble to
        SHR     DL,1            ; the low
        SHR     DL,1            ; position.
        CALL    J4
        MOV     DL,DH
J4:     AND     DL,0FH          ;Mask low nibble
        JZ      J5              ;If not zero
        MOV     CL,0
J5:     DEC     CH
        AND     CL,CH
        OR      DL,'0'          ;Fold in ASCII zero
        SUB     DL,CL
        DOSCALL @CHROUT         ;Print next digit
        RET                     ;Exit to caller
PRINTDD ENDP
 
J6      PROC    NEAR
        ADC     AL,AL
        DAA
        XCHG    AL,AH
        ADC     AL,AL
        DAA
        XCHG    AL,AH
        RET
J6      ENDP
 
        SUBTTL  PRINT DATE, TIME & # FILES ROUTINES
        PAGE
PRTDTE  PROC    NEAR    ;Print packed date in AX as MM/DD/YY
        OR      AX,AX
        JNZ     K1              ;If date <> 0
        DOSCALL @STROUT,SPACES-8 ;Print 8 spaces
        RET
K1:     PUSH    AX
        AND     AX,MASK P_MO    ;Mask the month,
        MOV     CL,P_MO         ; set shift count,
        SHR     AX,CL           ; right justify, &
        CALL    PRTBCD          ; print it.
        DOSCALL @CHROUT,'/'
        POP     AX
        PUSH    AX
        AND     AX,MASK P_DY    ;Mask the day &
        CALL    PRTBCD          ; print it.
        DOSCALL @CHROUT,'/'
        POP     AX
        AND     AX,MASK P_YR    ;Mask the year,
        MOV     CL,P_YR         ; set shift count,
        SHR     AX,CL           ; right justify,
        ADD     AX,80           ; add in year bias, &
                                ; print it.
PRTBCD: AAM                     ;Convert AL to BCD
        OR      AX,'00'         ;Convert to ASCII
        PUSH    AX
        DOSCALL @CHROUT,AH      ;High order digit
        POP     AX
        DOSCALL @CHROUT,AL      ;Low order digit
        RET
PRTDTE  ENDP
 
PRTTME  PROC    NEAR    ;Print packed time in AX as HH:MM
        OR      AX,AX
        JNZ     L1
        DOSCALL @STROUT,SPACES-5 ;Print 5 spaces
        RET
L1:     PUSH    AX
        AND     AX,MASK P_HR    ;Mask the hours,
        MOV     CL,P_HR         ; set shift count,
        SHR     AX,CL           ; right justify, &
        CALL    PRTBCD          ; print it.
        DOSCALL @CHROUT,':'
        POP     AX
        AND     AX,MASK P_MI    ;Mask the minutes,
        MOV     CL,P_MI         ; set shift count,
        SHR     AX,CL           ; right justify, &
        CALL    PRTBCD          ; print it.
        RET
PRTTME  ENDP
 
        PAGE
PRTNFLS PROC    NEAR    ;print number of files
        DOSCALL @STROUT,RED     ;setup color                        djm
        MOV     SI,NBRFILS      ;get # of files
        XOR     DI,DI           ;zero high order
        CALL    PRINTDD         ;Print # of files
        DOSCALL @STROUT,HDNG3
        MOV     SI,TOTL         ;set up total for print             djm
        MOV     DI,TOTH         ;                                   djm
        CALL    PRINTDD         ;print total space used by dir      djm
        DOSCALL @STROUT,HDNG5   ;                                   djm
        MOV     SI,LOSIZE       ;free space                         djm
        MOV     DI,HISIZE       ;                                   djm
        CALL    PRINTDD         ;print free space                   djm
        DOSCALL @STROUT,HDNG6   ;                                   djm
        RET
PRTNFLS ENDP
        EVEN
DIRBUF  DIRNTRY <>      ;Buffer for directory entries
SDIR    ENDS
        END     MAIN


Press ENTER to continue:  EVEN
DIRBUF  DIRNTRY <>      ;Buffer for directory entries
SDIR    ENDS
        END     MAIN


Press ENTER to co