    TITLE   SDIR - SORTED DIRECTORY COMMAND, Version 2.1
    PAGE    64,132                            ; JAN 1983
COMMENT |
    SDIR [d:][filename[.ext]] [options]
     [filespec] same as for DIR command

     [options] * /A - List hidden files.
               * /E - Without screen erase.
               * /P - Pause when screen full.
                 /X - Sort by extension.
                 /S - Sort by size.
                 /D - Sort by date/time.
                 /N - Do not sort, original order.

       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
    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.
|

    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

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

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      0       ;if <> 0 then pause if screen full
LPERSCR EQU 25      ;Lines per screen
LINCNT      DB      LPERSCR-4 ;Number of lines left
PSEMSG      DB      'Strike a key when ready . . . $'

HDNG1       DB      'Capital PC Software Exchange /AEPXSDN/ 2.2' ;   JYF
    DB      'DRIVE '
HDRVE       DB      '@:    Date '
D_MM        DW      '00'            ;Month
    DB      '/'
D_DD        DW      '00'            ;Day
    DB      '/'
D_YY        DW      '00'            ;Year
    DB      '  Time '
T_HH        DW      '00'            ;Hours
    DB      ':'
T_MM        DW      '00'            ;Minutes
    DB      CR,LF
CRLF    DB      CR,LF,'$'
HDNG2   DB      'FILESPEC.EXT  BYTES-  --LAST CHANGE--$'
        DB      8 DUP(' ')
SPACES  DB      '$'
HDNG3   DB      ' File(s)',CR,LF,'$'

        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

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:     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
        RET                     ;Return to DOS
MAIN    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    B10
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     B3              ;Nope, try next one.
        MOV     BYTE PTR ATTRIB,2+6  ;Hidden & system
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,'P'          ;Pause when screen full?
        JNZ     B9              ;Nope, try next one.
        MOV     PSEFLG,AL
B9:     LOOP    B2              ;Test for another param.
B10:    RET
GETARGS ENDP

        SUBTTL  SRCHDIR - SEARCH DIRECTORY
        PAGE
SRCHDIR PROC    NEAR
        DOSCALL @SETDTA,DTA     ;Set DTA for dir. search
        DOSCALL @SRCH1,XFCB     ;First call to search dir.
C1:     OR      AL,AL
        JNZ     C2              ;Not found, quit looking.
        MOV     BX,DIRLNK       ;BX <- base of DIRBUF
        LEA     DI,[BX].NAM
        MOV     SI,OFFSET FILNAME
        MOV     CX,SIZE NAM
        CLD
        REPZ    MOVSB           ;Move filename to DIRBUF
        MOV     BYTE PTR [DI],'.' ; Store a period
        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
        MOVSW                   ;Move size to DIRBUF
        MOVSW
        ADD     BX,SIZE DIRNTRY ;Point to next entry
        MOV     DIRLNK,BX       ;Save ptr
        INC     NBRFILS         ;Increment file count
        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
    PAGE
GETFREE PROC        NEAR            ;cluster = allocation unit
    MOV     DL,DRVNBR       ;Get drive #
    PUSH    DS              ;Save DS
    DOSCALL @GETVER         ;get DOS version number                    JYF
    CMP     AL,2            ;is this version 2.0 or higher?            JYF
    JGE     E4              ;yes                                       JYF
                            ;no                                        JYF
    DOSCALL @FATAD2         ;Get FAT info from DOS
    MOV     AH,0            ;AL = sector size
    XCHG    CX,DX           ;Sector size times the
    MUL     DX              ; # sectors/cluster
    PUSH    AX              ;Save cluster size
    XOR     AX,AX           ;Unused clusters = 0
    MOV     SI,2            ;Skip first 3 clusters
E1: MOV     DI,SI           ;DI <- cluster #
    SHR     DI,1            ;Divide cluster number
    ADD     DI,SI           ; by 1.5
    MOV     DI,[BX+DI]      ;Fetch from FAT
    TEST    SI,1            ;Test if even or odd
    JZ      E2              ;If even then skip
    SHR     DI,1            ; else if odd
    SHR     DI,1            ;  right justify the
    SHR     DI,1            ;  cluster number.
    SHR     DI,1
E2: AND     DI,0FFFH        ;Mask the low 12 bits
    JNZ     E3              ;If not 0 then skip, else
    INC     AX              ; increment counter.
E3: INC     SI              ;Point to next cluster
    LOOP    E1              ; and go check it.
    POP     CX              ;Get cluster size, times
    MUL     CX              ;  # of free clusters
    JMP     E5              ;skip processing for DOS 2.0                JYF
E4:                         ;processing for DOS 2.00                    JYF
    DOSCALL @DSKFSP         ;get disk free space                        JYF
    MUL     BX              ;AX (sectors/clustor) * BX (free clustors)  JYF
    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
    MOV     BX,C1LNK        ;Insert FREESPC in
    MOV     DI,OFFSET FREESPC ;first position
    MOV     [DI],BX         ; of linked list of
    MOV     C1LNK,DI        ; directory entries.
    INC     NBRFILS         ;Bump # of entries
    RET
GETFREE ENDP

    SUBTTL  PRTHDNG - PRINT HEADINGS
    PAGE
PRTHDNG PROC        NEAR
        MOV     AL,CLSFLG
        OR      AL,AL
        JNZ     G1              ;If not erase screen
        SUB     CX,CX
        MOV     DX,24*256+79    ;row=24 col=79
        MOV     BH,7            ;Video mode
        MOV     AX,0600H
        INT     10H             ;BIOS video call
        SUB     DX,DX
        MOV     AH,2            ;Clear screen
        MOV     BH,0
        INT     10H             ;BIOS video call
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,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     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.
        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
        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
        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

PRTNFLS PROC    NEAR    ;print number of files
        MOV     SI,NBRFILS      ;get # of files
        DEC     SI              ;-1 for free space
        XOR     DI,DI           ;zero high order
        CALL    PRINTDD         ;Print # of files
        DOSCALL @STROUT,HDNG3
        RET
PRTNFLS ENDP
        EVEN
DIRBUF  DIRNTRY <>      ;Buffer for directory entries
SDIR    ENDS
        END     MAIN
