home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sampler0 / sdir24c.asm < prev    next >
Assembly Source File  |  1984-02-06  |  47KB  |  930 lines

  1.     TITLE   SDIR - SORTED DIRECTORY COMMAND, Version 2.4
  2.     PAGE    64,132                            ; JAN 1983
  3. COMMENT |
  4.     SDIR [d:][path][filename[.ext]] [options]                           2.4
  5.      [filespec] same as for DIR command
  6.  
  7.      [options] * /A - List hidden files.
  8.                * /E - Without screen erase.
  9.                * /P - Pause when screen full.
  10.                  /X - Sort by extension.
  11.                  /S - Sort by size.
  12.                  /D - Sort by date/time.
  13.                  /N - Do not sort, original order.
  14.  
  15.        Default = *.* sorted by name.ext with screen erase.
  16.        * - Option may be combined with other options.
  17.  
  18.    This source file was created from an object file obtained
  19.  from Gene Plantz's BBS in Chicago. The original file name
  20.  was SD.HEX.  I then used DEBUG and CAPTURE to get the first
  21.  dis-assembly which  was then edited with WORDSTAR to create
  22.  a source that when assembled using MASM would duplicate the
  23.  original object file.
  24.    Comments have been added and I do hope they are helpful.
  25.  I have made several modifications to the first version and
  26.  am continuing to add comments.  This source file is an
  27.  excellent example for anyone wishing to learn 8086/8088
  28.  assembly language.  Use at your own risk and feel free to
  29.  share this file with your friends.
  30.    I certainly wish that John Chapman would publish his
  31.  source file.  His comments are sure to be more meaningful
  32.  than mine could ever be.  Some of the conversion routines
  33.  are very elegant, but difficult to understand.  As far as
  34.  I'm concerned, PRINTDD is magic.
  35.    Several modifications have been made.  They are:
  36.  
  37.         1. Filespecs are processed like DIR does.
  38.         2. No sort option was added. /N
  39.         3. Pause when screen full option added. /P
  40.     4. Number of files found is printed.
  41.  
  42.                                     Ted Reuss
  43.                                     Houston, TX
  44.  
  45.     SDIR Version 2.2  The GETFREE Subroutine was updated for DOS 2.0
  46.     April 1, 1983   by   Jack Y. Fong
  47.     Changes are denoted by "JYF" at the end of changed lines.
  48.  
  49.  
  50.         SDIR Version 2.3:
  51.         Added display of current directory name and volume name
  52.                 in header lines for DOS Release 2.0.
  53.         Added total of file sizes for the displayed files.
  54.                 This is helpful in DOS 2.0 since it allows you to determine
  55.                 the number of bytes used by all the files in a root or
  56.                 subdirectory (or used by a specified subset of
  57.                 the files in a root or subdirectory).
  58.  
  59.         John F. Ratti   29 June, 1983
  60.         Changes are denoted by "2.3" at the end of the changed lines.
  61.  
  62.         SDIR Version 2.4:
  63.         Added display of attribute byte. The column 'ATR' will display
  64.                 up to 4 attribute codes. The codes are as follows:
  65.                 A - Archive bit is off (file has been archived)
  66.                 H - Hidden bit is on (file is hidden)
  67.                 R - Read-only bit is on (file is read-only)
  68.                 S - System bit is on (file is a system file)
  69.         Corrected display of hidden, system, read-only and directory
  70.                 entries when /a option is specified.
  71.         Added pathname capability. Any pathname that DIR will accept
  72.                 will work. The code should have been rewritten, rather than
  73.                 modified. The resulting code is somewhat obtuse, and I
  74.                 apologize for it. I plan to write a proper pathname
  75.                 parser. When I do, I'll incorporate it into SDIR.
  76.         This version MUST be used under MS-DOS release 2.0.
  77.         John F. Ratti   03 July, 1983
  78.         Changes are denoted by "2.4" at the end of the changed lines.
  79. |
  80.  
  81.     SUBTTL  EQUATES & STRUCTURES
  82.     PAGE
  83. IF1
  84. DOSCALL MACRO       FUNC,PARM1
  85. .xcref
  86. F_C =       FUNC
  87. IFNB <PARM1>
  88. 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
  89.     MOV     DL,PARM1
  90. ELSE
  91.     MOV     DX,OFFSET PARM1
  92. ENDIF
  93. ENDIF
  94.         MOV     AH,FUNC
  95.         INT     21H
  96. .cref
  97.         ENDM
  98. ENDIF
  99. .SALL   ;supress all macro expansions
  100. ;       PC-DOS INTERRUPT 21H FUNCTION CODES
  101. ;
  102. @CHROUT EQU     2       ;display char in DL
  103. @KEYIN  EQU     8       ;kybd input w/o echo
  104. @STROUT EQU     9       ;print string terminated with $
  105. @CKEYIN EQU     12      ;clr kybd bufr & do inp.func in AL
  106. @OPEN   EQU     15      ;open XFCB                                      2.4
  107. @SRCH1  EQU     17      ;search for first dir entry
  108. @SRCH2  EQU     18      ;search for next dir entry
  109. @GETDSK EQU     25      ;get default disk drive
  110. @SETDTA EQU     26      ;set disk transfer addr
  111. @FATAD2 EQU     28      ;get FAT of drive # in DL
  112. @PARSEF EQU     41      ;parse filename
  113. @GETDTE EQU     42      ;get system date
  114. @GETTME EQU     44      ;get system time
  115. @GETVER EQU     30H     ;get version number                             JYF
  116. @CTLBRK EQU     33H     ;get/set ctrl/break checking                    2.4
  117. @DSKFSP EQU     36H     ;get disk free space                            JYF
  118. @CHDIR  EQU     3BH     ;change directory                               2.4
  119. @CHMOD  EQU     43H     ;change/get file mode                           2.4
  120. @GETCD  EQU     47H     ;get current directory                          2.3
  121. @FIND1  EQU     4EH     ;find first dir. entry (DOS 2.0)                2.4
  122. @FIND2  EQU     4FH     ;find next dir entry (DOS 2.0)                  2.4
  123.  
  124. CR  EQU     0DH     ;carriage return
  125. LF  EQU     0AH     ;line feed
  126. FCB_1       EQU     5CH     ;fcb for parameter 1
  127. PARAM_L EQU 80H     ;# characters in PARAM_B
  128. PARAM_B EQU 81H     ;DOS cmd parameter buffer.
  129.  
  130. ; PC-DOS packed date   <yyyyyyym mmmddddd>
  131. P_DTE       RECORD  P_YR:7,P_MO:4,P_DY:5
  132. ; PC-DOS packed time   <hhhhhmmm mmmsssss>
  133. P_TME       RECORD  P_HR:5,P_MI:6,P_2S:5
  134.  
  135. DIR      RECORD  P_YR:7,P_MO:4,P_DY:5
  136. ; PC-DOS packed time   <hhhhhmmm mmmsssss>
  137. P_TME       RECORD  P_HR:5,P_MI:6,P_2S:5
  138.  
  139. DIRNTRY STRUC               ;directory entry structure
  140. LNK DW      0       ;ptr to next entry
  141. NAM DB      8 DUP(0),'.' ;filename
  142. EXT DB      3 DUP(0) ;extension
  143. TME DW      0       ;time
  144. DTE     DW      0       ;date
  145. SZL     DW      0       ;low word of size
  146. SZH     DW      0       ;high word of size
  147. ATR     DB      0       ;attribute byte                                 2.4
  148. DIRNTRY ENDS
  149.  
  150.         SUBTTL  DATA AREA & INITIALIZATION
  151.         PAGE
  152. SDIR    SEGMENT PUBLIC 'CODE'
  153.         ASSUME  CS:SDIR,DS:SDIR,ES:SDIR
  154.         ORG     100H
  155. MAIN    PROC    FAR
  156.         JMP     STARTS
  157.  
  158. DIRLNK  DW      DIRBUF  ;ptr to next opening in DIRBUF
  159. C1LNK   DW      0       ;ptr to row 1, column 1
  160. C2LNK   DW      0       ;ptr to row 1, column 2
  161. NBRFILS DW      0       ;# of files or detail lines
  162. SRTFLG  DB      0       ;if = 0 then sort else no sort
  163. CLSFLG      DB      0       ;if = 0 then clear screen
  164. EXTFLG      DB      0       ;if <> 0 then sort by ext
  165. SIZFLG      DB      0       ;if <> 0 then sort by size
  166. DTEFLG      DB      0       ;if <> 0 then sort by date/time
  167. PSEFLG      DB      0       ;if <> 0 then pause if screen full
  168. LPERSCR EQU 25      ;Lines per screen
  169. LINCNT      DB      LPERSCR-5 ;Number of lines left
  170. PSEMSG      DB      'Strike a key when ready . . . $'
  171.  
  172. HDNG1       DB      'SDIR: Sorted DIRectory listing, Version 2.4  ';   2.3
  173.             DB      'Volume '            ;                             2.3
  174. VOLNAME     DB      '             ' ;                                  2.3
  175. D_MM        DW      '00'            ;Month
  176.     DB      '/'
  177. D_DD        DW      '00'            ;Day
  178.     DB      '/'
  179. D_YY        DW      '00'            ;Year
  180.     DB      ' '
  181. T_HH        DW      '00'            ;Hours
  182.     DB      ':'
  183. T_MM        DW      '00'            ;Minutes
  184.             DB      CR,LF,'$'       ;                                  2.3
  185. HDNG2       DB      32 DUP(' ')     ;                                  2.3
  186.             DB      'Directory of ' ;                                  2.3
  187. HDRVE       DB      '@:'            ;                                  2.3
  188. DIRNAME     DB      '\',69 DUP(0)       ; directory name                2.4
  189.             DB      LF,LF,CR,'$'    ;                                  2.3
  190. CRLF    DB      CR,LF,'$'
  191. LFLFCR  DB      LF,LF,CR,'$'            ;literal for a blank line       2.3
  192. HDNG3   DB      'FILESPEC.EXT  BYTES ATR -LAST  CHANGE-$'
  193.         DB      8 DUP(' ')
  194. SPACES  DB      '$'
  195. HDNG4   DB      ' Bytes in $'                   ;                       2.3
  196. HDNG5   DB      ' File(s); ','$'                ;                       2.4
  197. HDNG6   DB      ' bytes free.',CR,LF,'$'        ;                       2.4
  198.  
  199.         SUBTTL  DISK TRANSFER AREA & FREE SPACE ENTRY DEFS
  200.         PAGE
  201.  
  202.         DB      'PATH NAME='
  203. PATHD   DB      '@:'
  204. PATH    DB      64 DUP(0)       ;hold area for pathname                 2.4
  205.  
  206. XFCB    DB      -1,7 DUP(0),11 DUP('?'),25 DUP(0)
  207. ATTRIB  EQU     XFCB+6          ;file attribute
  208. DRVNUM  EQU     ATTRIB+1        ;drive # (1=A, 2=B, etc.)
  209.  
  210. DTA     DB      40 DUP(0)       ;Disk Transfer Area used
  211. XNAME   EQU     DTA+8           ;volume name                            2.4
  212. FILNAME EQU     DTA+30          ;by FIND for the                        2.4
  213. FILTIME EQU     DTA+22          ;directory search.                      2.4
  214. FILSIZE EQU     DTA+26          ;                                       2.4
  215. FILATTR EQU     DTA+21          ;(file attribute byte)                  2.4
  216.  
  217. FREESPC DW      0               ;Free space entry.
  218.         DB      '*FREE SPACE*',4 DUP(0)
  219. LOSIZE  DW      0               ;of free space
  220. HISIZE  DW      0               ;of free space
  221.  
  222. LOTOTAL DW      0               ;total size of all files: low word      2.3
  223. HITOTAL DW      0               ;total size of all files: high word     2.3
  224.  
  225. PATHLEN DW      0               ;length of subdirectories in pathname   2.4
  226. HOLDATR DB      0               ;hold area for XFCB attribute byte      2.3
  227. HOLDLEN DW      0               ;hold area for length of directory name 2.3
  228.  
  229. DBLCNT  DW      0               ;current offset into DOUBLE             2.4
  230. DOUBLE  DB      8 DUP(' '),'$'  ;destination for PRINTDX                2.4
  231.  
  232. PRTATR  DB      5 DUP(' '),'$'  ;area to build ATR for printing         2.4
  233. INITATR DB      5 DUP(' ')      ;used to re-init ATR                    2.4
  234.  
  235. PRTDIR 2DB      '  <DIR>$'      ;literal used to denote directories     2.4
  236. ALLF    DB      '*.*'           ;literal for displaying all files       2.4
  237. PATHALL DB      '\*.*',0        ;same as above for subdirectories       2.4
  238.  
  239. DRVNBR  DB      0               ;place to hold working drive number     2.4
  240.  
  241. CURDSK  DB      '@:\'           ;hold area for current dirname so we can2.4
  242. CURDIR  DB      64 DUP(0)       ;restore it later                       2.4
  243.  
  244. PATHNF  DB      'Path not found$' ;error message literal                2.4
  245.  
  246.         SUBTTL  MAIN PROGRAM SECTION
  247.         PAGE
  248. STARTS:
  249.         PUSH    DS              ;Set up the
  250.         XOR     AX,AX           ; stack for a
  251.         PUSH    AX              ; return to DOS.
  252.         CALL    GETARGS         ;Process arguments
  253.         CALL    SRCHDIR         ;Search directory
  254.         CMP     SRTFLG,0        ;Check if any sort
  255.         JZ      A1              ; option selected.
  256.         CALL    LNKDIRB         ;Leave in original
  257.         JMP     SHORT A2        ; directory order.
  258. A1:     CALL    SRTDIRB         ;Sort by major key
  259. A2:     CALL    GETFREE         ;Get free space
  260.         CALL    SPLTLST         ;Set up for 2 columns
  261.         CALL    PRTHDNG         ;Print headings
  262.         CALL    PRTDRVR         ;Print detail lines
  263.         CALL    PRTNFLS         ;Print byte total and # of files        2.3
  264.         RET                     ;Return to DOS
  265. MAIN    ENDP
  266.  
  267.         SUBTTL  GETARGS - PROCESS ARGUMENTS
  268.         PAGE
  269. GETARGS PROC    NEAR
  270.         MOV     DI,PARAM_L      ;point to command buffer length         2.4
  271.         XOR     CH,CH           ;clear high-order byte                  2.4
  272.         MOV     CL,BYTE PTR [DI] ;get length                            2.4
  273.         JCXZ    G24F            ;jump if no param provided              2.4
  274.         INC     DI              ;point to command buffer                2.4
  275.         MOV     AL,' '          ;we'll search for the first non-blank   2.4
  276.         CLD                     ;search forward                         2.4
  277.         REPE    SCASB           ;find first non-blank                   2.4
  278.         JE      G24F            ;all blanks: treat like no parm provided2.4
  279.         INC     CX              ;and adjust length                      2.4
  280.         DEC     DI              ;adjust offset                          2.4
  281.         MOV     SI,DI           ;save offset of first non-blank         2.4
  282.         MOV     DX,CX           ;save cx                                2.4
  283.         MOV     AL,'/'          ;search for a slash                     2.4
  284.         REPNE   SCASB           ;search for a slash                     2.4
  285.         JCXZ    G24A            ;jump if slash not found                2.4
  286.         INC     CX              ;adjust cx if slash found               2.4
  287. G24A:   NEG     CX              ;subtract count from original length    2.4
  288.         ADD     CX,DX           ;to get length of drive+path            2.4
  289.         JCXZ    G24F            ;if 0, only options specified           2.4
  290.         MOV     DI,OFFSET PATH  ;point to path name hold area           2.4
  291.         CMP     BYTE PTR [SI+1],':' ;was drive number specified?        2.4
  292.         JNE     G24B            ;No, go move the path                   2.4
  293.         INC     SI              ;point past drive number                2.4
  294.         INC     SI              ;point past :                           2.4
  295.         DEC     CX              ;adjust...                              2.4
  296.         DEC     CX              ;...length                              2.4
  297.         JNZ     G24B            ;if any characters remain process them  2.4
  298. G24F:   MOV     SI,OFFSET ALLF  ;point to the all-files literal         2.4
  299.         MOV     DI,OFFSET PATH  ;the path needs it                      2.4
  300.         MOV     CX,3            ;length of literal                      2.4
  301.         CLD                     ;to assure forward direction            2.4
  302.         REP     MOVSB           ;move the literal                       2.4
  303.         JMP     G24C            ;now process normally                   2.4
  304. G24B:   CLD                     ;clear direction flag                   2.4
  305.         MOV     DX,CX           ;save the length                        2.4
  306.         REP     MOVSB           ;and move the pathname to path          2.4
  307.         CMP     DX,1            ;is length of pathname 1?               2.4
  308.         JNE     G24C            ;no                                     2.4
  309.         CMP     PATH,'\'        ;is the only character a backslash?     2.4
  310.         JNE     G24C            ;no                                     2.4
  311.         MOV     SI,OFFSET ALLF  ;point to the all-files literal         2.4
  312.         MOV     DI,OFFSET PATH+1 ;the path needs it                     2.4
  313.         MOV     CX,3            ;length of literal                      2.4
  314.         CLD                     ;to assure forward direction            2.4
  315.         REP     MOVSB           ;move the literal                       2.4
  316. G24C:   MOV     SI,PARAM_B      ;point to cmd buffer                    2.4
  317.         MOV     DI,OFFSET DRVNUM ;point to FCB                          2.4
  318.         MOV     AL, 1111B       ;Select parse options
  319.         DOSCALL @PARSEF         ;Parse filename
  320.         CMP     BYTE PTR [DI],0 ;If <> 0 then
  321.         JNZ     B1              ; not default drive
  322.         DOSCALL @GETDSK         ;AL <- default disk
  323.         INC     AL              ;Increment drive #
  324.         STOSB                   ;Save drive #
  325. B1:     MOV     AL,DRVNUM       ;get drive number                       2.4
  326.         MOV     DRVNBR,AL       ;save as working drive number           2.4
  327.         ADD     PATHD,AL        ;convert drive number to ascii          2.4
  328.         XOR     CX,CX           ;clear cx just in case...               2.4
  329.         MOV     AX,0            ;load "get attribute" subfunction code  2.4
  330.         DOSCALL @CHMOD,PATHD    ;get attribute of the current path in cx2.4
  331.         OR      AL,AL           ;check for error                        2.4
  332.         JNZ     G24X            ;if so, it's not a directory            2.4
  333.         TEST    CX,10H          ;is it a directory?                     2.4
  334.         JZ      G24X            ;no                                     2.4
  335.         MOV     DI,OFFSET PATH  ;we need to find the end of PATH        2.4
  336.         MOV     CX,64           ;which can be up to 64 bytes long...    2.4
  337.         MOV     AL,0            ;...so we'll search for a 0             2.4
  338.         CLD                     ;search forward                         2.4
  339.         REPNE   SCASB           ;find the end of PATH                   2.4
  340.         DEC     DI              ;point di at the zero                   2.4
  341.         MOV     SI,OFFSET PATHALL ;point to literal                     2.4
  342.         MOV     CX,5            ;literal is 5 bytes long                2.4
  343.         CLD                     ;i'm a coward                           2.4
  344.         REP     MOVSB           ;now move the literal to the path       2.4
  345. G24X:   MOV     CX,64           ;up to 64 characters in a pathname      2.4
  346.         MOV     AL,'\'          ;we'll search for the last backslash    2.4
  347.         MOV     DI,OFFSET PATH+63 ;point to the end of the pathname     2.4
  348.         STD                     ;search backwards                       2.4
  349.         REPNE   SCASB           ;for the last backslash                 2.4
  350.         MOV     PATHLEN,CX      ;and save path length                   2.4
  351.         CMP     PATH,'\'        ;is first path character a backslash?   2.4
  352.         JNE     G24D            ;no, full path not specified            2.4
  353.         MOV     CX,PATHLEN      ;get the length of the subdirectories   2.4
  354.         MOV     SI,OFFSET PATH  ;point to path                          2.4
  355.         MOV     DI,OFFSET DIRNAME ;and to dest                          2.4
  356.         CLD                     ;just in case                           2.4
  357.         REP     MOVSB           ;move the pathname                      2.4
  358.         JMP     G24E            ;bypass the rest of this                2.4
  359. G24D:   MOV     SI,OFFSET DIRNAME+1 ;point to directory name field      2.4
  360.         MOV     DL,BYTE PTR DRVNBR ;pick up drive number                2.4
  361.         DOSCALL @GETCD          ;get the current directory              2.4
  362.         MOV     CX,PATHLEN      ;if pathlen is zero, no subdirectories  2.4
  363.         JCXZ    G24E            ;so don't concatenate path              2.4
  364.         MOV     CX,64           ;we're going to find the end of...      2.4
  365.         MOV     AL,0            ;...DIRNAME so we can concatenate...    2.4
  366.         MOV     DI,OFFSET DIRNAME ;...the path subdirectories to it     2.4
  367.         CLD                     ;search forwards                        2.4
  368.         REPNE   SCASB           ;search for a 0                         2.4
  369.         DEC     DI              ;point back to the zero                 2.4
  370.         DEC     DI              ;point to last character of current dir 2.4
  371.         CMP     BYTE PTR [DI],'\' ;is the last character a backslash?   2.4
  372.         JNE     G24Z            ;no, it's not a root directory          2.4
  373.         INC     DI              ;adjust pointer                         2.4
  374.         JMP     G24Y            ;and skip extra-separator stuff         2.4
  375. G24Z:   INC     DI              ;adjust pointer                         2.4
  376.         MOV     AL,'\'          ;get a literal                          2.4
  377.         STOSB                   ;to separate the 2 concatenated parts   2.4
  378. G24Y:   MOV     CX,PATHLEN      ;get length of subdirectories           2.4
  379.         MOV     SI,OFFSET PATH  ;move from path to dirname              2.4
  380.         CLD                     ;forward move                           2.4
  381.         REP     MOVSB           ;now concatenate the dir + pathnames    2.4
  382. G24E:   MOV     AL,0            ;read ctrl/break state into dl          2.4
  383.         DOSCALL @CTLBRK         ;read status                            2.4
  384.         PUSH    DX              ;save status                            2.4
  385.         MOV     AL,1            ;prepare to set ctl/break state...      2.4
  386.         MOV     DL,0            ;...to OFF...                           2.4
  387.         DOSCALL @CTLBRK         ;...so we won't mess up the current dir 2.4
  388.         MOV     DL,BYTE PTR DRVNBR ;get drive number                    2.4
  389.         ADD     CURDSK,DL       ;convert to ascii                       2.4
  390.         ADD     HDRVE,DL        ;convert to ascii                       2.4
  391.         MOV     SI,OFFSET CURDIR ;point to current directory save area  2.4
  392.         DOSCALL @GETCD          ;get and save current directory         2.4
  393.         DOSCALL @CHDIR,HDRVE    ;temporarily set current directory      2.4
  394.         CMP     AL,3            ;check for error return                 2.4
  395.         JNE     G24Q            ;jump if no error                       2.4
  396.         DOSCALL @STROUT,PATHNF  ;issue 'path not found message'         2.4
  397.         INT     20H             ;and get lost                           2.4
  398. G24Q:   MOV     DL,BYTE PTR DRVNBR ;get drive number                    2.4
  399.         MOV     SI,OFFSET DIRNAME+1 ;point to dirname                   2.4
  400.         DOSCALL @GETCD          ;now get the dirname without '\..'s     2.4
  401.         DOSCALL @CHDIR,CURDSK   ;now reset the current directory        2.4
  402.         MOV     AL,1            ;set ctrl/break state...                2.4
  403.         POP     DX              ;...to previous value                   2.4
  404.         DOSCALL @CTLBRK         ;and do it                              2.4
  405.         MOV     DI,OFFSET DIRNAME ;point to directory name field again  2.4
  406.         MOV     CX,64           ;name can be up to 64 bytes long        2.4
  407.         MOV     AL,0            ;name is terminated by a zero           2.4
  408.         CLD                     ;just in case                           2.4
  409.         REPNE   SCASB           ;search for the end                     2.4
  410.         MOV     AX,64           ;get constant                           2.4
  411.         SUB     AX,CX           ;subtract remaining count               2.4
  412.         SHR     AX,1            ;divide result by 2                     2.4
  413.         MOV     HOLDLEN,AX      ;and save result                        2.4
  414.         DEC     DI              ;adjust pointer                         2.4
  415.         MOV     CX,4            ;load length of literal                 2.4
  416.         MOV     SI,OFFSET LFLFCR ;point to literal                      2.4
  417.         CLD                     ;just in case                           2.4
  418.         REP     MOVSB           ;and terminate the dirname with literal 2.4
  419.         MOV     SI,PARAM_L      ;SI <- ptr cmd length
  420.         MOV     CH,0
  421.         MOV     CL,[SI]         ;CL <- # chars in cmd
  422.         JCXZ    B10
  423. B2:     INC     SI              ;Point to next char
  424.         CMP     BYTE PTR [SI],'/'
  425.         JNZ     B8              ;If not a slash
  426.         MOV     AL,[SI+1]       ;AL <- option letter
  427.         AND     AL,0DFH         ;Force to upper-case
  428.         CMP     AL,'A'          ;Hidden & system & directory files?
  429.         JNZ     B3              ;Nope, try next one.
  430.         MOV     HOLDATR,2+4+16 ;Hidden & system & directory
  431. B3:     CMP     AL,'E'          ;Without screen erase?
  432.         JNZ     B4              ;Nope, try next one.
  433.         MOV     CLSFLG,AL
  434. B4:     CMP     AL,'S'          ;Sort by size?
  435.         JNZ     B5              ;Nope, try next one.
  436.         MOV     SIZFLG,AL
  437. B5:     CMP     AL,'D'          ;Sort by date/time?
  438.         JNZ     B6              ;Nope, try next one.
  439.         MOV     DTEFLG,AL
  440. B6:     CMP     AL,'X'          ;Sort by extension?
  441.         JNZ     B7              ;Nope, try next one.
  442.         MOV     EXTFLG,AL
  443. B7:     CMP     AL,'N'          ;Original order?
  444.         JNZ     B8              ;Nope, try next one.
  445.         MOV     SRTFLG,AL
  446. B8:     CMP     AL,'P'          ;Pause when screen full?
  447.         JNZ     B9              ;Nope, try next one.
  448.         MOV     PSEFLG,AL
  449. B9:     LOOP    B2              ;Test for another param.
  450. B10:    RET
  451. GETARGS ENDP
  452.  
  453.         SUBTTL  SRCHDIR - SEARCH DIRECTORY
  454.         PAGE
  455. SRCHDIR PROC    NEAR
  456.  
  457.         DOSCALL @SETDTA,DTA     ;Set DTA for dir. search                2.3
  458.         MOV     CX,11           ;we'll move 11...                       2.4
  459.         MOV     AL,'?'          ;...question marks...                   2.4
  460.         MOV     DI,OFFSET XFCB+8 ;...to the XFCB...                     2.4
  461.         CLD                     ;...in case the filename is crashed...  2.4
  462.         REP     STOSB           ;...so that we can search for the volid 2.4
  463.         MOV     BYTE PTR ATTRIB,8 ;set attribute byte and...            2.3
  464.         DOSCALL @SRCH1,XFCB     ;get the volume name                    2.3
  465.         MOV     SI,OFFSET XNAME ;point to filename within xfcb          2.4
  466.         MOV     CX,11           ;load length of volume name             2.3
  467.         MOV     DI,OFFSET VOLNAME ;point to destination field in HDNG1  2.3
  468.         CLD                     ;forward, march                         2.3
  469.         REP     MOVSB           ;move the volume name                   2.3
  470.         MOV     DI,OFFSET DIRNAME ;point to the directory name again    2.3
  471.         MOV     CL,HOLDATR      ;get the real attribute byte            2.4
  472.         XOR     CH,CH           ;clear the high-order byte              2.4
  473.         DOSCALL @FIND1,PATHD    ;First call to search dir.              2.4
  474. C1:     OR      AL,AL
  475.         JNZ     C2              ;Not found, quit looking.
  476.         MOV     BX,DIRLNK       ;BX <- base of DIRBUF
  477.         LEA     DI,[BX].NAM     ;point to beginning of dirntry          2.4
  478.         MOV     SI OFFSET FILNAME
  479.         MOV     CX,12           ;length of filename                     2.4
  480.         CMP     BYTE PTR [SI],'.' ;is first character a period?         2.4
  481.         JNE     C24A            ;no, it's not a special case            2.4
  482.         MOVSB                   ;move it to the buffer                  2.4
  483.         DEC     CX              ;adjust count                           2.4
  484.         CMP     BYTE PTR [SI],'.' ;is next character a period?          2.4
  485.         JNE     C24A            ;no, let normal routine pad the rest    2.4
  486.         MOVSB                   ;move it to the buffer                  2.4
  487.         DEC     CX              ;adjust count                           2.4
  488. C24A:   CMP     BYTE PTR [SI],0 ;is it a zero?                          2.4
  489.         JNE     C24B            ;no                                     2.4
  490.         MOV     AL,' '          ;load a space into al                   2.4
  491.         REP     STOSB           ;and blank out the rest of the name     2.4
  492.         JMP     C24X            ;and go get other fields                2.4
  493. C24B:   CMP     BYTE PTR [SI],'.' ;is it a period?                      2.4
  494.         JNE     C24C            ;no, process it                         2.4
  495.         MOV     DX,CX           ;save CX                                2.4
  496.         SUB     CX,4            ;determine number of spaces needed      2.4
  497.         SUB     DX,CX           ;adjust saved CX                        2.4
  498.         MOV     AL,' '          ;get a space                            2.4
  499.         REP     STOSB           ;and pad out the name                   2.4
  500.         MOV     CX,DX           ;restore CX                             2.4
  501. C24C:   MOVSB                   ;move the character to the buffer       2.4
  502.         DEC     CX              ;adjust count                           2.4
  503.         JNZ     C24A            ;and loop if anything's left to process 2.4
  504. C24X:   MOV     SI,OFFSET FILTIME ;exit point for filename routine      2.4
  505.         MOVSW                   ;Move time to DIRBUF
  506.         MOVSW                   ;Move date to DIRBUF
  507.         MOV     SI,OFFSET FILSIZE
  508.         MOVSW                   ;Move size to DIRBUF
  509.         MOVSW
  510.         MOV     SI,OFFSET FILATTR ;point to file attribute byte         2.4
  511.         MOVSB                   ;and move it to dirntry                 2.4
  512.         ADD     BX,SIZE DIRNTRY ;Point to next entry
  513.         MOV     DIRLNK,BX       ;Save ptr
  514.         INC     NBRFILS         ;Increment file count
  515.         MOV     CL,HOLDATR      ;get the real attribute byte            2.4
  516.         XOR     CH,CH           ;clear the high-order byte              2.4
  517.         DOSCALL @FIND2,PATHD    ;Search for next file                   2.4
  518.         JMP     C1              ;Loop for next one
  519. C2:     RET
  520. SRCHDIR ENDP
  521.  
  522.         SUBTTL  SRTDIRB - SORTS ENTRIES IN DIRBUF
  523.         PAGE
  524. SRTDIRB PROC    NEAR    ;Sorts directory entries in DIRBUF
  525.         MOV     DI,OFFSET DIRBUF ;Point to DIRBUF
  526. D1:     CMP     DI,DIRLNK       ;Are there anymore?
  527.         JNC     D8              ;NO, exit
  528.         MOV     SI,OFFSET C1LNK ;Start with column 1 ptr
  529. D2:     MOV     BX,SI
  530.         MOV     SI,[BX]         ;SI<-ptr to next entry
  531.         OR      SI,SI
  532.         JZ      D7              ;if link=0
  533.         MOV     AX,SI
  534.         MOV     DX,DI
  535.         XOR     CL,CL           ;CL <- 0
  536.         CMP     CL,SIZFLG
  537.         JNZ     D5              ;If sort by size
  538.         CMP     CL,DTEFLG
  539.         JNZ     D4              ;If sort by date/time
  540.         CMP     CL,EXTFLG
  541.         JNZ     D3              ;If sort by ext
  542.         LEA     SI,[SI].NAM
  543.         LEA     DI,[DI].NAM
  544.         MOV     CX,1+SIZE NAM+SIZE EXT  ;# of bytes
  545.         JMP     SHORT D6
  546. D3:     LEA     SI,[SI].EXT     ;Sort by extension
  547.         LEA     DI,[DI].EXT
  548.         MOV     CX,SIZE EXT     ;# of bytes
  549.         JMP     SHORT D6
  550. D4:     LEA     SI,[SI].DTE     ;Sort by date/time
  551.         LEA     DI,[DI].DTE
  552.         MOV     CX,2            ;# of words
  553.         STD
  554.         REPZ    CMPSW
  555.         MOV     DI,DX
  556.         MOV     SI,AX
  557.         JBE     D2
  558.         JMP     SHORT D7
  559. D5:     LEA     SI,[SI].SZH     ;Sort by size
  560.         LEA     DI,[DI].SZH
  561.         MOV     CX,2            ;# of words
  562.         STD
  563.         REPZ    CMPSW
  564.         MOV     DI,DX
  565.         MOV     SI,AX
  566.         JBE     D2
  567.         JMP     SHORT D7
  568. D6:     CLD                     ;Sort by name.ext
  569.         REPZ    CMPSB
  570.         MOV     DI,DX
  571.         MOV     SI,AX
  572.         JBE     D2
  573. D7:     MOV     [DI],SI
  574.         MOV     [BX],DI
  575.         ADD     DI,SIZE DIRNTRY ;Point to next entry
  576.         JMP     D1
  577. D8:     RET
  578. SRTDIRB ENDP
  579.  
  580.         SUBTTL
  581.         PAGE
  582. ; LNKDIRB - LINKS ENTRIES IN DIRBUF
  583.  
  584. LNKDIRB PROC    NEAR            ;LINK ENTRIES IN DIRBUF
  585.         MOV     DI,OFFSET DIRBUF
  586.         MOV     C1LNK,DI       ;Point to 1st entry
  587.         MOV     CX,NBRFILS      ;Set loop counter
  588.         DEC     CX
  589. LNK1:   MOV     BX,DI
  590.         ADD     DI,SIZE DIRNTRY ;Offset to next entry
  591.         MOV     [BX],DI         ;Store ptr
  592.         LOOP    LNK1            ;Link next entry
  593.         MOV     [DI],CX         ;Last ptr <- null
  594.         RET
  595. LNKDIRB ENDP
  596.  
  597. ; SPLTLST - SPLITS LINKED LIST IN HALF
  598.  
  599. SPLTLST PROC    NEAR
  600.         MOV     CX,NBRFILS      ;Get # of entries
  601.         SAR     CX,1            ; and divide by 2
  602.         JZ      F2              ;if NBRFILS < 2
  603.         ADC     CL,0            ;Account for odd #
  604.         MOV     BX,OFFSET C1LNK
  605. F1:     MOV     BX,[BX]         ;Chain thru list to
  606.         LOOP    F1              ; last row of column 1.
  607.         MOV     AX,[BX]         ;Get ptr to 1st row of col 2
  608.         MOV     C2LNK,AX        ; C2LNK <- R1,C2 ptr
  609.         MOV     [BX],CX         ;Last row of col 1 <- null
  610. F2:     RET
  611. SPLTLST ENDP
  612.  
  613.         SUBTTL  GETFREE - GET DISK FREE SPACE
  614.     PAGE
  615. GETFREE PROC        NEAR            ;cluster = allocation unit
  616.     MOV     DL,DRVNBR       ;Get drive #
  617.     PUSH    DS              ;Save DS
  618.     DOSCALL @GETVER         ;get DOS version number                    JYF
  619.     CMP     AL,2            ;is this version 2.0 or higher?            JYF
  620.     JGE     E4              ;yes                                       JYF
  621.                             ;no                                        JYF
  622.     DOSCALL @FATAD2         ;Get FAT info from DOS
  623.     MOV     AH,0            ;AL = sector size
  624.     XCHG    CX,DX           ;Sector size times the
  625.     MUL     DX              ; # sectors/cluster
  626.     PUSH    AX              ;Save cluster size
  627.     XOR     AX,AX           ;Unused clusters = 0
  628.     MOV     SI,2            ;Skip first 3 clusters
  629. E1: MOV     DI,SI           ;DI <- cluster #
  630.     SHR     DI,1            ;Divide cluster number
  631.     ADD     DI,SI           ; by 1.5
  632.     MOV     DI,[BX+DI]      ;Fetch from FAT
  633.     TEST    SI,1            ;Test if even or odd
  634.     JZ      E2              ;If even then skip
  635.     SHR     DI,1            ; else if odd
  636.     SHR     DI,1            ;  right justify the
  637.     SHR     DI,1            ;  cluster number.
  638.     SHR     DI,1
  639. E2: AND     DI,0FFFH        ;Mask the low 12 bits
  640.     JNZ     E3              ;If not 0 then skip, else
  641.     INC     AX              ; increment counter.
  642. E3: INC     SI              ;Point to next cluster
  643.     LOOP    E1              ; and go check it.
  644.     POP     CX              ;Get cluster size, times
  645.     MUL     CX              ;  # of free clusters
  646.     JMP     E5              ;skip processing for DOS 2.0                JYF
  647. E4:                         ;processing for DOS 2.00                    JYF
  648.     DOSCALL @DSKFSP         ;get disk free space                        JYF
  649.     MUL     BX              ;AX (sectors/clustor) * BX (free clustors)  JYF
  650.     MOV     DX,AX           ;                                           JYF
  651.     MUL     CX              ;AX * CX (bytes/clustor)          Æ        JYF
  652. E5:                         ;                                           JYF
  653.     POP     DS              ;Restore DS
  654.     MOV     LOSIZE,AX       ;Save the 32 bit
  655.     MOV     HISIZE,DX       ; binary free space
  656.     RET
  657. GETFREE ENDP
  658.  
  659.     SUBTTL  PRTHDNG - PRINT HEADINGS
  660.     PAGE
  661. PRTHDNG PROC        NEAR
  662.         MOV     AL,CLSFLG
  663.         OR      AL,AL
  664.         JNZ     G1              ;If not erase screen
  665.         SUB     CX,CX
  666.         MOV     DX,24*256+79    ;row=24 col=79
  667.         MOV     BH,7            ;Video mode
  668.         MOV     AX,0600H
  669.         INT     10H             ;BIOS video call
  670.         SUB     DX,DX
  671.         MOV     AH,2            ;Clear screen
  672.         MOV     BH,0
  673.         INT     10H             ;BIOS video call
  674. G1:     MOV     AL,DRVNBR       ;Get drive #
  675.         DOSCALL @GETDTE ; CX<-year, DH<-month, DL<-day
  676.         MOV     AL,DH
  677.         AAM
  678.         XCHG    AL,AH
  679.         OR      D_MM,AX         ;Fold into month
  680.         MOV     AL,DL
  681.         AAM
  682.         XCHG    AL,AH
  683.         OR      D_DD,AX         ;Fold into day
  684.         MOV     AX,CX
  685.         SUB     AX,1900
  686.         AAM
  687.         XCHG    AL,AH
  688.         OR      D_YY,AX         ;Fold into year
  689.         DOSCALL @GETTME ; CH<-hours, CL<-minutes
  690.         MOV     AL,CH           ;AL<-binary hours
  691.         AAM                     ;Convert AL to two
  692.         XCHG    AL,AH           ; BCD digits in AX.
  693.         OR      T_HH,AX         ;Fold into hours
  694.         MOV     AL,CL           ;AL<-binary minutes
  695.         AAM                     ;Convert AL to two
  696.         XCHG    AL,AH           ; BCD digits in AX.
  697.         OR      T_MM,AX         ;Fold into minutes
  698.         DOSCALL @STROUT,HDNG1   ;Print main heading
  699.         MOV     DX,OFFSET HDNG2 ;point to 2nd heading                   2.3
  700.         ADD     DX,HOLDLEN      ;add offset length to center DIRNAME    2.3
  701.         DOSCALL @STROUT         ;Print subheading                       2.3
  702.         DOSCALL @STROUT,HDNG3   ;Print column 1 heading
  703.         CMP     WORD PTR C2LNK,0
  704.         JZ      G2              ;If not 2 columns
  705.         DOSCALL @STROUT,SPACES-3 ;Print 3 spaces                        2.4
  706.         DOSCALL @STROUT,HDNG3   ;Print column 2 heading
  707. G2:     DOSCALL @STROUT,CRLF    ;Start a new line
  708.         RET
  709. PRTHDNG ENDP
  710.  
  711.         SUBTTL  PRINT DETAIL LINES
  712.         PAGE
  713. PRTDRVR PROC    NEAR            ;Driver routine
  714.         MOV     BX,C1LNK
  715.         OR      BX,BX           ;more to print?
  716.         JZ      H2              ; no, return
  717.         MOV     AX,[BX]
  718.         MOV     C1LNK,AX
  719.         CALL    PRTDTL          ;print column one
  720.         MOV     BX,C2LNK
  721.         OR      BX,BX
  722.         JZ      H1              ;If no column 2 entry
  723.         DOSCALL @STROUT,SPACES-3 ;print 3 spaces                        2.4
  724.         MOV     AX,[BX]
  725.         MOV     C2LNK,AX
  726.         CALL    PRTDTL          ;print column two
  727. H1:     DOSCALL @STROUT,CRLF
  728.         CMP     PSEFLG,0        ;Check for pause option
  729.         JZ      PRTDRVR         ;Nope, continue
  730.         DEC     LINCNT          ;Decrement line counter
  731.         JNZ     PRTDRVR         ;If page not full?
  732.         MOV     LINCNT,LPERSCR-2 ;Reset to # lines/screen
  733.         DOSCALL @STROUT,PSEMSG  ;Display pause message.
  734.         MOV     AL,@KEYIN       ;Specify input function
  735.         DOSCALL @CKEYIN         ;Wait for key press
  736.         DOSCALL @STROUT,CRLF    ;Set to newline
  737.         JMP     PRTDRVR         ;Go do the next line
  738. H2:     RET
  739. PRTDRVR ENDP
  740.  
  741. PRTDTL  PROC    NEAR            ;Prints file.ext, size, date & time
  742.         MOV     CX,1+SIZE NAM+SIZE EXT  ;                               2.4
  743.         SUB     DI,DI           ;DI <- 0
  744. I1:     DOSCALL @CHROUT,[BX+DI].NAM
  745.         INC     DI              ;point to next char.
  746.         LOOP    I1              ;go do next char.
  747.         TEST    BYTE PTR [BX].ATR,10H ;is it a directory entry?         2.4
  748.         JZ      I2              ;no, print size                         2.4
  749.         DOSCALL @STROUT,PRTDIR  ;yes, print <DIR> instead of size       2.4
  750.         JMP     I3              ;and bypass size print                  2.4
  751. I2:     PUSH    BX              ;save entry base
  752.         MOV     SI,[BX].SZL     ;SI <- low size
  753.         MOV     DI,[BX].SZH     ;DI <- high size
  754.         ADD     LOTOTAL,SI      ;add low-order word to total            2.3
  755.         ADC     HITOTAL,DI      ;and add high-order word to total       2.3
  756.         CALL    PRINTDX         ;convert size                           2.4
  757.         MOV     DX,OFFSET DOUBLE+1 ;point past first byte of decimal #  2.4
  758.         DOSCALL @STROUT         ;Print size                             2.4
  759.         POP     BX              ;restore entry base
  760. I3:     MOV     CX,5            ;we need to move 5 bytes                2.4
  761.         MOV     SI,OFFSET INITATR ;to initialize PRTATR                 2.4
  762.         MOV     DI,OFFSET PRTATR  ;with spaces                          2.4
  763.         CLD                     ;just in case                           2.4
  764.         REP     MOVSB           ;now move the spaces                    2.4
  765.         TEST    BYTE PTR [BX].ATR,10H ;is it a directory file?          2.4
  766.         JNZ     I24X            ;yes, bypass the other tests            2.4
  767.         MOV     DI,OFFSET PRTATR+3 ;point to right side of field        2.4
  768.         STD                     ;and work backwards                     2.4
  769.         TEST    BYTE PTR [BX].ATR,20H ;is it an archived file?          2.4
  770. ;note that the archive bit is set OFF when the file is archived...      2.4
  771.         JNZ     I24H            ;no, test for hidden file               2.4
  772.         MOV     AL,'A'          ;get flag character                     2.4
  773.         STOSB                   ;and put it into PRTATR                 2.4
  774. I24H:   TEST    BYTE PTR [BX].ATR,02H ;is it a hidden file?             2.4
  775.         JZ      I24R            ;no, test for r/o file                  2.4
  776.         MOV     AL,'H'          ;get flag character                     2.4
  777.         STOSB                   ;and put it into PRTATR                 2.4
  778. I24R:   TEST    BYTE PTR [BX].ATR,01H ;is it a r/o file?                2.4
  779.         JZ      I24S            ;no, test for system file               2.4
  780.         MOV     AL,'R'          ;get flag character                     2.4
  781.         STOSB                   ;and put it into PRTATR                 2.4
  782. I24S:   TEST    BYTE PTR [BX].ATR,04H ;is it a system file?             2.4
  783.         JZ      I24X            ;no, exit tests                         2.4
  784.         MOV     AL,'S'          ;get flag character                     2.4
  785.         STOSB                   ;and put it into PRTATR                 2.4
  786. I24X:   DOSCALL @STROUT,PRTATR  ;Print the attribute characters         2.4
  787.         MOV     AX,[BX].DTE     ;AX <- packed date
  788.         CALL    PRTDTE
  789.         DOSCALL @STROUT,SPACES-1 ;print 1 space                         2.4
  790.         MOV     AX,[BX].TME     ;AX <- packed time
  791.         CALL    PRTTME
  792.         RET
  793. PRTDTL  ENDP
  794.  
  795.         SUBTTL  PRINTDD - PRINT A DOUBLE WORD IN DI:SI
  796.         PAGE
  797. PRINTDD PROC    NEAR            ;Prints a 32 bit integer in DI:SI
  798.         CALL    PRINTDX         ;format the double word into DOUBLE     2.4
  799.         DOSCALL @STROUT,DOUBLE  ;print the digits                       2.4
  800.         RET                     ;and return                             2.4
  801. PRINTDD ENDP                    ;                                       2.4
  802.  
  803. PRINTDX PROC    NEAR            ;converts integer in DI:SI to decimal   2.4
  804.         MOV     DBLCNT,0        ;reset the offset for DOUBLE            2.4
  805.         XOR     AX,AX           ;Zero out the                           2.4
  806.         MOV     BX,AX           ; working
  807.         MOV     BP,AX           ; registers.
  808.         MOV     CX,32           ;# bits of precision
  809. J1:     SHL     SI,1
  810.         RCL     DI,1
  811.         XCHG    BP,AX
  812.         CALL    J6
  813.         XCHG    BP,AX
  814.         XCHG    BX,AX
  815.         CALL    J6
  816.         XCHG    BX,AX
  817.         ADC     AL,0
  818.         LOOP    J1
  819.         MOV     CX,1710H        ;5904 ?
  820.         MOV     AX,BX
  821.         CALL    J2
  822.         MOV     AX,BP
  823. J2:     PUSH    AX
  824.         MOV     DL,AH
  825.         CALL    J3
  826.         POP     DX
  827. J3:     MOV     DH,DL
  828.         SHR     DL,1            ;Move high
  829.         SHR     DL,1            ; nibble to
  830.         SHR     DL,1            ; the low
  831.         SHR     DL,1            ; position.
  832.         CALL    J4
  833.         MOV     DL,DH
  834. J4:     AND     DL,0FH          ;Mask low nibble
  835.         JZ      J5              ;If not zero
  836.         MOV     CL,0
  837. J5:     DEC     CH
  838.         AND     CL,CH
  839.         OR      DL,'0'          ;Fold in ASCII zero
  840.         SUB     DL,CL
  841.         PUSH    DI              ;save DI                                2.4
  842.         MOV     DI,OFFSET DOUBLE ;point to DOUBLE                       2.4
  843.         ADD     DI,DBLCNT       ;add current offset                     2.4
  844.         INC     DBLCNT          ;bump offset for next time              2.4
  845.         MOV     BYTE PTR [DI],DL ;move next digit to DOUBLE             2.4
  846.         POP     DI              ;restore DI                             2.4
  847.         RET                     ;Exit to caller
  848. PRINTDX ENDP                    ;                                       2.4
  849.  
  850. J6      PROC    NEAR
  851.         ADC     AL,AL
  852.         DAA
  853.         XCHG    AL,AH
  854.         ADC     AL,AL
  855.         DAA
  856.         XCHG    AL,AH
  857.         RET
  858. J6      ENDP
  859.  
  860.         SUBTTL  PRINT DATE, TIME & # FILES ROUTINES
  861.         PAGE
  862. PRTDTE  PROC    NEAR    ;Print packed date in AX as MM/DD/YY
  863.         OR      AX,AX
  864.         JNZ     K1              ;If date <> 0
  865.         DOSCALL @STROUT,SPACES-8 ;Print 8 spaces
  866.         RET
  867. K1:     PUSH    AX
  868.         AND     AX,MASK P_MO    ;Mask the month,
  869.         MOV     CL,P_MO         ; set shift count,
  870.         SHR     AX,CL           ; right justify, &
  871.         CALL    PRTBCD          ; print it.
  872.         DOSCALL @CHROUT,'/'
  873.         POP     AX
  874.         PUSH    AX
  875.         AND     AX,MASK P_DY    ;Mask the day &
  876.         CALL    PRTBCD          ; print it.
  877.         DOSCALL @CHROUT,'/'
  878.         POP     AX
  879.         AND     AX,MASK P_YR    ;Mask the year,
  880.         MOV     CL,P_YR         ; set shift count,
  881.         SHR     AX,CL           ; right justify,
  882.         ADD     AX,80           ; add in year bias, &
  883.                                 ; print it.
  884. PRTBCD: AAM                     ;Convert AL to BCD
  885.         OR      AX,'00'         ;Convert to ASCII
  886.         PUSH    AX
  887.         DOSCALL @CHROUT,AH      ;High order digit
  888.         POP     AX
  889.         DOSCALL @CHROUT,AL      ;Low order digit
  890.         RET
  891. PRTDTE  ENDP
  892.  
  893. PRTTME  PROC    NEAR    ;Print packed time in AX as HH:MM
  894.         OR      AX,AX
  895.         JNZ     L1
  896.         DOSCALL @STROUT,SPACES-5 ;Print 5 spaces
  897.         RET
  898. L1:     PUSH    AX
  899.         AND     AX,MASK P_HR    ;Mask the hours,
  900.         MOV     CL,P_HR         ; set shift count,
  901.         SHR     AX,CL           ; right justify, &
  902.         CALL    PRTBCD          ; print it.
  903.         DOSCALL @CHROUT,':'
  904.         POP     AX
  905.         AND     AX,MASK P_MI    ;Mask the minutes,
  906.         MOV     CL,P_MI         ; set shift count,
  907.         SHR     AX,CL           ; right justify, &
  908.         CALL    PRTBCD          ; print it.
  909.         RET
  910. PRTTME  ENDP
  911.  
  912. PRTNFLS PROC    NEAR            ;print byte total and number of files   2.3
  913.         MOV     SI,LOTOTAL      ;get low-order word of total            2.3
  914.         MOV     DI,HITOTAL      ;get high-order word of total           2.3
  915.         CALL    PRINTDD         ;and print the total                    2.3
  916.         DOSCALL @STROUT,HDNG4   ;follow the total with a message        2.3
  917.         MOV     SI,NBRFILS      ;get # of files
  918.         XOR     DI,DI           ;zero high order
  919.         CALL    PRINTDD         ;Print # of files
  920.         DOSCALL @STROUT,HDNG5   ;follow it with a heading
  921.         MOV     SI,LOSIZE       ;get low-order word of freespace        2.4
  922.         MOV     DI,HISIZE       ;get high-order word of freespace       2.4
  923.         CALL    PRINTDD         ;and print freespace                    2.4
  924.         DOSCALL @STROUT,HDNG6   ;follow the freespace with explanation  2.4
  925.         RETèP@TNFLS ENDP
  926.         EVEN
  927. DIRBUF  DIRNTRY <>      ;Buffer for directory entries
  928. SDIR    ENDS
  929.         END     MAIN
  930.