               TITLE   TOUCH
               Page    60,132
;--------------------------------------------------------------------
;  TOUCH - Set the time/date entry for a file.
;  PC Magazine - Michael J. Mefford
;--------------------------------------------------------------------
_TEXT          SEGMENT PUBLIC 'CODE'          ;********************************;
               ASSUME  CS:_TEXT,DS:_TEXT      ;*                              *;
                                              ;*  Requires MASM 2.0 or later  *;
               ORG     80H + 22               ;*     Remember to EXE2BIN      *;
FILE_TIME      DW      ?                      ;*                              *;
FILE_DATE      DW      ?                      ;********************************;
FILE_SIZE_LOW  DW      ?
FILE_SIZE_HIGH DW      ?
FILE_NAME      DB      ?

               ORG     100H
START:         JMP     MAIN

CR             EQU     13
LF             EQU     10
CTRL_Z         EQU     26
SPACE          EQU     32

;              DATA AREA
;              ---------
               DB      CR,SPACE,SPACE,SPACE,CR,LF
COPYRIGHT      DB      "TOUCH 1.0 (c) 1988 Ziff Communications Co.",CR,LF
PROGRAMMER     DB      "PC Magazine ",254," Michael J. Mefford",CR,LF,"$"

SYNTAX         DB      CR,LF
               DB      CR,LF,"Syntax:  TOUCH filespec [/D date] [/T time]"
               DB      CR,LF,"date = month-day-year"
               DB      CR,LF,"time = hour[:minutes[:seconds]]"
               DB      CR,LF,"Default is system date and time."
CR_LF          DB      CR,LF,"$"
               DB      CTRL_Z


DATE_FLAG      EQU     1
TIME_FLAG      EQU     2

CURRENT_DISK   DB      ?
PATH_END       DW      ?

SWITCH_FLAG    DB      0
SWITCH_DATE    DW      0
SWITCH_TIME    DW      0
SYSTEM_DATE    DW      ?
SYSTEM_TIME    DW      ?
TOUCH_DATE     DW      ?
TOUCH_TIME     DW      ?

SYNTAX_MSG     DB      "Invalid parameter$"
NOT_FOUND_MSG  DB      "File not found$"


DELIMITERS     DB      ":-/"


;              CODE AREA
;              ---------

;------------------------------------------------------------------------;
; First task is to save the current drive and directory defaults.        ;
; We will be changing the defaults and wish to restore them on exit.     ;
; The system date and time is retrieved, compressed, and stored to stamp ;
; the file if no switch request found.  Carriage return linefeed combo   ;
; sent to display to put air between DOS prompt and TOUCH's messages.    ;
;------------------------------------------------------------------------;

MAIN           PROC    NEAR

               CLD                             ;String moves forward.

               MOV     AH,9
               MOV     DX,OFFSET COPYRIGHT
               INT     21H

               MOV     AH,19H                  ;Get current drive
               INT     21H
               MOV     CURRENT_DISK,AL         ; and save.
               MOV     BYTE PTR CURRENT_DIR,"\"   ;DOS doesn't preface directory
               MOV     SI,OFFSET CURRENT_DIR + 1  ; with slash so we must.
               XOR     DL,DL
               MOV     AH,47H                     ;Get current directory.
               INT     21H

               MOV     AH,2AH                  ;Get current date
               INT     21H
               CALL    CONVERT_DATE            ; compress
               MOV     SYSTEM_DATE,DX          ; and store.
               MOV     AH,2CH                  ;Get current time and do same.
               INT     21H
               CALL    CONVERT_TIME
               MOV     SYSTEM_TIME,DX

               MOV     DX,OFFSET CR_LF         ;Send carriage return linefeed
               MOV     AH,9                    ; to display just to make our
               INT     21H                     ; output pretty.

;-----------------------------------------------------------------------;
; Parse the command line for date or time switches.  If found, compress ;
; decimal number to hex format required by DOS to set date and time.    ;
;-----------------------------------------------------------------------;

               MOV     SI,81H                  ;Point to command line parameter.
FIND_SWITCH:   LODSB                           ;Get a byte.
               CMP     AL,CR                   ;Carriage return marks end.
               JZ      FILESPEC                ;If end, done here.
               CMP     AL,"/"                  ;Is it a switch character?
               JNZ     FIND_SWITCH             ;If no, next byte.
               LODSB                           ;Else, retrieve switch.
               CMP     AL,CR                   ;Did user omit character?
               JZ      FILESPEC                ;If yes, done here.
               AND     AL,5FH                  ;Else, capitalize.
               CMP     AL,"D"                  ;Is it date switch?
               JNZ     CK_TIME                 ;If no, check if time.
               OR      SWITCH_FLAG,DATE_FLAG   ;Else, flag that date included.
               CALL    PARSE_LEADING           ;Parse off leading delimiters.
               CALL    GET_NUMBER              ;Get first number.
               JZ      BAD_PARAMETER           ;Was it a zero or no number?
               MOV     DH,BL                   ;If yes, exit, else store month.
               CALL    GET_NUMBER              ;Get next number.
               JZ      BAD_PARAMETER           ;Was it zero?
               MOV     DL,BL                   ;If yes, exit, else store day.
               CALL    GET_NUMBER              ;Get last number.
               JZ      BAD_PARAMETER           ;Was it zero?
               MOV     CX,BX                   ;If yes, exit, else store year.
               CALL    CONVERT_DATE            ;Convert decimal to compressed
               MOV     SWITCH_DATE,DX          ; hex number and store.
               JMP     SHORT FIND_SWITCH       ;Check for another switch.

CK_TIME:       CMP     AL,"T"                  ;Is there a time switch?
               JNZ     FIND_SWITCH             ;If no, check next byte.
               OR      SWITCH_FLAG,TIME_FLAG   ;Else, flag that time included.
               CALL    PARSE_LEADING           ;Handle same as date.
               CALL    GET_NUMBER
               MOV     DH,BL                   ;Store hour in DH.
               CALL    GET_NUMBER
               MOV     DL,BL                   ;Store minutes in DL.
               CALL    GET_NUMBER
               MOV     CX,DX                   ;Store hour and minutes in CX.
               MOV     DH,BL                   ;Store seconds in DH.
               CALL    CONVERT_TIME            ;Convert
               MOV     SWITCH_TIME,DX          ; and store.

               JMP     SHORT FIND_SWITCH       ;Check for next switch.

;-----------------------------------------;
; Lily pad for short jumps to error exit. ;
;-----------------------------------------;

BAD_PARAMETER: JMP     SYNTAX_EXIT             ;Error jumping address.

;------------------------------------------------------------------;
; Parse drive and/or path delimiters.  Convert filespec to ASCIIZ. ;
; If drive delimiter found (:), change to requested drive.         ;
;------------------------------------------------------------------;

FILESPEC:      MOV     SI,81H                  ;Point to command line parameter.
               CALL    PARSE_LEADING           ;Parse off leading delimiters.
               PUSH    SI                      ;Save start of filename.
               XOR     BX,BX                   ;Use BX as path specifier flag.
FIND_END:      LODSB                           ;Get a byte.
               CMP     AL,":"                  ;Is it a drive delimiter?
               JNZ     CK_PATH                 ;If no, check if path delimiter.
               MOV     DL,[SI-2]               ;Else, retrieve drive specifier.
               AND     DL,5FH                  ;Capitalize.
               SUB     DL,"A"                  ;Convert to DOS format.
               MOV     AH,0EH                  ;Change drive.
               INT     21H
               MOV     BX,SI                   ;Save as possible filename start.
               JMP     SHORT FIND_END

CK_PATH:       CMP     AL,"\"                  ;Is it a path delimiter?
               JNZ     CK_DELIMITER            ;If no, check switch character.
               MOV     BX,SI                   ;Else, save as possible filename.
CK_DELIMITER:  CMP     AL,"/"                  ;Is it a switch delimiter?
               JZ      FOUND_END               ;If yes, end of filespec.
               CMP     AL,SPACE                ;Is it above space character?
               JA      FIND_END                ;If yes, continue until find end.
FOUND_END:     MOV     BYTE PTR [SI-1],0       ;Else, convert to ASCIIZ.

;------------------------------------------------------------------;
; Save the working default directory so we can restore it on exit. ;
; If path was found, change to requested directory.                ;
;------------------------------------------------------------------;

               MOV     BYTE PTR WORKING_DIR,"\"   ;DOS doesn't preface directory
               MOV     SI,OFFSET WORKING_DIR + 1  ; with slash so we must.
               XOR     DL,DL
               MOV     AH,47H                  ;Get current directory
               INT     21H                     ; of working drive.

               POP     DX                      ;Retrieve filespec start.
               OR      BX,BX                   ;Was there a path specifier?
               JZ      FIND_FILE               ;If no, done here.
               CMP     BYTE PTR [BX-1],":"     ;Was it a drive specifier only?
               JZ      FIND_FILE               ;If yes, done here.
               PUSH    BX                      ;Else, save as filename start.
               CMP     BYTE PTR [BX-2],":"     ;Was it "d:\"?
               JZ      CHANGE_DIR              ;If yes, no adjust.
               CMP     BYTE PTR [BX-2],SPACE   ;Was it plain root "\"?
               JBE     CHANGE_DIR              ;If yes, no adjust.
               DEC     BX                      ;Else point to path delimiter.
CHANGE_DIR:    PUSH    [BX]                    ;Save first byte of filename.
               MOV     BYTE PTR [BX],0         ;Temporary zero so ASCIIZ path.
               MOV     AH,3BH                  ;Change directory.
               INT     21H
               POP     [BX]                    ;Restore first byte of filename.
               POP     DX                      ;Retrieve filename pointer.

;------------------------------------------------------------------------;
; Ready for business.  Find the file and get a filehandle by opening the ;
; file for reading.  If no matching filename is found, exit with error   ;
; message.  If no switch characters were found, then update file with    ;
; system date and time.  Else, touch with requested value.  If only one  ;
; switch request was made, don't change the other.  Display results.     ;
;------------------------------------------------------------------------;

FIND_FILE:     MOV     CX,7                    ;Attribute of all files.
               MOV     AH,4EH                  ;Find first matching file.
               INT     21H
               JNC     TOUCH_FILE                ;If found, change date/time.
               MOV     DX,OFFSET NOT_FOUND_MSG   ;Else, display error message
               JMP     SHORT MESSAGE_EXIT        ; and exit.

FIND_NEXT:     MOV     AH,4FH                  ;Find next matching file.
               INT     21H
               JC      GOOD_EXIT               ;If failed, we're done.
TOUCH_FILE:    MOV     DX,OFFSET FILE_NAME     ;Else, open file for reading
               MOV     AX,3D00H                ; to get a filehandle.
               INT     21H
               MOV     BX,AX                   ;Filehandle needs to be in BX.

               MOV     CX,SYSTEM_TIME          ;Assume request to update
               MOV     DX,SYSTEM_DATE          ; to system date and time.
               MOV     AL,SWITCH_FLAG          ;Retrieve the switch flag.
               CMP     AL,0                    ;Was there a switch?
               JZ      SET_DATE_TIME           ;If no, assumed right.
               MOV     CX,SWITCH_TIME          ;Else, assume it a time request.
               TEST    AL,TIME_FLAG            ;Was there a time switch?
               JNZ     DO_DATE                 ;If yes, assumed right.
               MOV     CX,FILE_TIME            ;Else, use file's time.

DO_DATE:       MOV     DX,SWITCH_DATE          ;Assume there was a date request.
               TEST    AL,DATE_FLAG            ;Was there a date switch?
               JNZ     SET_DATE_TIME           ;If yes, assumed right.
               MOV     DX,FILE_DATE            ;Else, use file's date.

SET_DATE_TIME: MOV     TOUCH_TIME,CX           ;Save date and time for
               MOV     TOUCH_DATE,DX           ; display purposes.
               MOV     AX,5701H                ;Set file's date and time.
               INT     21H
               JC      SYNTAX_EXIT             ;If failed, exit with message.

CLOSE_FILE:    MOV     AH,3EH                  ;Close the file.
               INT     21H
               CALL    DISPLAY_NAME            ;Display complete stats of file.
               JMP     SHORT FIND_NEXT         ;Find next file.

;--------------------------------------------------------------------;
; Display error message and TOUCH syntax if necessary.  Restore      ;
; working directory and default drive and directory.  Exit with      ;
; error code of one if problem; error code of zero if all went well. ;
;--------------------------------------------------------------------;

SYNTAX_EXIT:   MOV     DX,OFFSET SYNTAX_MSG    ;Display "Invalid parameters".
MESSAGE_EXIT:  MOV     AH,9
               INT     21H
               MOV     DX,OFFSET SYNTAX        ;Display TOUCH syntax message.
               MOV     AH,9
               INT     21H
               MOV     AL,1                    ;Exit with error code of 1.
               JMP     SHORT EXIT

GOOD_EXIT:     XOR     AL,AL                   ;Exit with error code of 0.
EXIT:          PUSH    AX                      ;Save error code.
               MOV     DX,OFFSET WORKING_DIR   ;Restore working directory.
               MOV     AH,3BH
               INT     21H
               MOV     DL,CURRENT_DISK         ;Restore default drive.
               MOV     AH,0EH
               INT     21H
               MOV     DX,OFFSET CURRENT_DIR   ;Restore default drive directory.
               MOV     AH,3BH
               INT     21H
               POP     AX                      ;Retrieve error code.
               MOV     AH,4CH
               INT     21H                     ;Terminate.

MAIN           ENDP

               ;***************;
               ;* SUBROUTINES *;
               ;***************;

;---------------------------------------------------;
; INPUT                                             ;
;   CX = Year  (1980 - 2099)                        ;
;   DH = Month (1 - 12)                             ;
;   DL = Day   (1 - 31)                             ;
;                                                   ;
; OUTPUT                                            ;
;   DX = compressed date in directory entry format. ;
;                                                   ;
;        <     DH      > <     DL      >            ;
;        y y y y y y y m m m m d d d d d            ;
;                                                   ;
;              y = year  (0 - 119)                  ;
;              m = month (1 - 12)                   ;
;              d = day   (1 - 31)                   ;
;                                                   ;
;   BX, CX destroyed.                               ;
;---------------------------------------------------;

CONVERT_DATE   PROC    NEAR

               SUB     CX,80                   ;Compress year.
               CMP     CX,1900                 ;Did user abbreviate year?
               JB      SAVE_MONTH              ;If yes, OK.
               SUB     CX,1900                 ;Else, subtract century part.
SAVE_MONTH:    MOV     BL,DH                   ;Store month in BL.
               XOR     BH,BH                   ;Zero in high half.
               SHL     CL,1                    ;Right justify year.
               MOV     DH,CL                   ;Store in DH.
               MOV     CL,5                    ;Shift month left 5 bits.
               SHL     BX,CL
               OR      DX,BX                   ;Add year and month to days.
               RET

CONVERT_DATE   ENDP

;---------------------------------------------------;
; INPUT                                             ;
;   CH = Hour    (0 - 23)                           ;
;   CL = Minutes (0 - 59)                           ;
;   DH = Seconds (0 - 59)                           ;
;                                                   ;
; OUTPUT                                            ;
;   DX = compressed time in directory entry format. ;
;                                                   ;
;        <     DH      > <     DL      >            ;
;        h h h h h m m m m m m x x x x x            ;
;                                                   ;
;              h = hour    (0 - 23)                 ;
;              m = minutes (0 - 59)                 ;
;              x = two-second increments (0 - 28)   ;
;                                                   ;
;   BX, CX destroyed.                               ;
;---------------------------------------------------;

CONVERT_TIME   PROC    NEAR

               MOV     BX,CX                   ;Store hour and min. in BX so we   
               MOV     CL,9                    ; can use CL as shift register.
               SHR     DX,CL                   ;Right justify; divide secs by 2.
               MOV     CL,3                    ;Justify left hour.
               SHL     BH,CL
               MOV     DH,BH                   ;Store hour in DH.
               MOV     CL,5
               SHL     BX,CL                   ;Justify minutes.
               OR      DX,BX                   ;Add minutes to hour and seconds.
               RET

CONVERT_TIME   ENDP

;----------------------------------------;
; INPUT                                  ;
;   DS:SI points to ASCII number string. ;
;                                        ;
; OUTPUT                                 ;
;   BX = hexidecimal number.             ;
;   DS:SI points to byte after string.   ;
;   If (ZF) = 1  --  BX =  0             ;
;   If (ZF) = 0  --  BX <> 0             ;
;                                        ;
;   AX, BX, CX, DI destroyed.            ;
;----------------------------------------;

GET_NUMBER     PROC    NEAR

               XOR     BX,BX                   ;Start with zero.
PARSE_DELIMIT: LODSB                           ;Get a byte.
               MOV     DI,OFFSET DELIMITERS    ;Is it a delimiter?
               MOV     CX,3
               REPNZ   SCASB
               JZ      PARSE_DELIMIT           ;If yes, get next byte.

               MOV     CL,10
NEXT_NUMBER:   XOR     AH,AH                   ;Zero in high half.
               CMP     AL,CR                   ;Is byte a carriage return?
               JZ      NUMBER_END              ;If yes, done.
               CMP     AL,"0"                  ;Is byte a number?
               JB      NUMBER_END
               CMP     AL,"9"
               JA      NUMBER_END              ;If no, done.
               SUB     AL,"0"                  ;Else, convert to hex.
               XCHG    AX,BX                   ;Store in BX.
               MUL     CL                      ;Multiply accumulated by 10.
               ADD     BX,AX                   ;Add new number.
               LODSB                           ;Next byte.
               JMP     SHORT NEXT_NUMBER

NUMBER_END:    DEC     SI                      ;Adjust pointer to delimiter.
               OR      BX,BX                   ;Set zero flag if results zero.
               RET

GET_NUMBER     ENDP

;--------------------------------------------------------;
; Parses off leading string delimiters.                  ;
; If carriage return encountered, jump directly to exit. ;
;                                                        ;
; INPUT                                                  ;
;   DS:SI points to ASCII string.                        ;
;                                                        ;
; OUTPUT                                                 ;
;   DS:SI points to first non-delimiting byte in string. ;
;                                                        ;
;   All registers preserved.                             ;
;--------------------------------------------------------;

PARSE_LEADING  PROC    NEAR

               LODSB                           ;Get a byte.
               CMP     AL,SPACE                ;Is it a space char or below?
               JA      LEADING_END             ;If no, done here.
               CMP     AL,CR                   ;Is it carriage return?
               JNZ     PARSE_LEADING           ;If no, get next byte.
               JMP     SYNTAX_EXIT             ;Else, immediate error exit.
LEADING_END:   DEC     SI                      ;Adjust pointer to string start.
               RET

PARSE_LEADING  ENDP

;------------------------------------------;
; Stores a filename in DOS DIR format.     ;
; That is, filename, bytes, date and time. ;
; Results are printed to display.          ;
;                                          ;
; USES                                     ;
;   FILE_NAME           TOUCH_DATE         ;
;   FILE_SIZE_LOW       TOUCH_TIME         ;
;   FILE_SIZE_HIGH      CR_LF              ;
;                                          ;
; CALLS                                    ;
;   STORE_WORD                             ;
;                                          ;
; OUTPUT                                   ;
;   RESULTS = filename DIR style format.   ;
;                                          ;
;   AX, BX, CX, DX, SI, DI destroyed.      ;
;------------------------------------------;

DISPLAY_NAME   PROC    NEAR

               MOV     SI,OFFSET FILE_NAME     ;Point to filename.
               MOV     DI,OFFSET RESULTS       ;And storage area.
               MOV     AL,SPACE                ;Initiate storage with spaces.
               MOV     CX,40
               REP     STOSB
               MOV     DI,OFFSET RESULTS       ;Point to start of storage again.
               MOV     CX,12                   ;Store 12 bytes of filename.
NEXT_STORE:    LODSB                           ;Get a byte.
               CMP     AL,0                    ;End of filename?
               JZ      END_STORE               ;If yes, finish with blanks.
               CMP     AL,"."                  ;Is it the period?
               JNZ     STORE_BYTE              ;If no, store.
               SUB     CX,3                    ;Else store 3 spaces.
               MOV     AL,SPACE
               REP     STOSB
               ADD     CX,3
               JMP     SHORT NEXT_STORE        ;Get next byte.

STORE_BYTE:    STOSB                           ;Store byte.
               LOOP    NEXT_STORE              ;Get next byte.
END_STORE:     MOV     AL,SPACE                ;Pad balance with spaces.
               REP     STOSB

               PUSH    DI                      ;Save pointer.
               ADD     DI,8                    ;Move to end of bytes field.
               MOV     DX,FILE_SIZE_LOW        ;Retrieve high and low words
               MOV     AX,FILE_SIZE_HIGH       ; of bytes.
               MOV     BX,10                   ;Convert to decimal.
               STD                             ;Reverse direction.

NEXT_SIZE:     MOV     CX,DX                   ;Low word in CX.
               XOR     DX,DX                   ;Zero in high half.
               DIV     BX                      ;Convert to decimal.
               XCHG    AX,CX                   ;Retrieve low word.
               DIV     BX
               XCHG    AX,DX                   ;Retrieve remainder.
               ADD     AL,"0"                  ;Convert to ASCII.
               STOSB                           ;Store it.
               MOV     AX,CX                   ;Are we done?
               OR      CX,DX
               JNZ     NEXT_SIZE               ;If no, divide again.

               CLD                             ;Back to forward direction.
               POP     DI                      ;Retrieve pointer.
               ADD     DI,11                   ;Move to date field.
DATE:          MOV     DX,TOUCH_DATE           ;Retrieve date.
               MOV     AX,DX
               MOV     CL,5                    ;Shift to lowest bits.
               SHR     AX,CL
               AND     AX,1111B                ;Mask off all but month.
               MOV     CL,0FFH                 ;Flag as no leading zeros.
               MOV     CH,"-"                  ;Delimiting character.
               CALL    STORE_WORD              ;Store it.

               MOV     AX,DX                   ;Retrieve date.
               AND     AX,11111B               ;Mask off all but day.
               XOR     CL,CL                   ;Flag include leading zeros.
               MOV     CH,"-"
               CALL    STORE_WORD              ;Store it.

               MOV     AX,DX                   ;Retrieve date for last time.
               MOV     CL,9
               SHR     AX,CL                   ;Mask off all but year.
               ADD     AX,80                   ;Adjust to ASCII.
               CMP     AX,100                  ;Past year 2000?
               JB      DISPLAY_DATE            ;If no, display. Else, adjust for
               SUB     AX,100                  ; next century. (Planning ahead!)
DISPLAY_DATE:  XOR     CL,CL                   ;Display leading zeros.
               MOV     CH,SPACE
               CALL    STORE_WORD              ;Store it.

TIME:          INC     DI                      ;Move to time field.
               MOV     DX,TOUCH_TIME           ;Retrieve time.
               MOV     AX,DX
               MOV     CL,11                   ;Shift to hours bits.
               SHR     AX,CL
               PUSH    AX
               CMP     AX,12                   ;Past noon?
               JBE     MERIDIAN
               SUB     AX,12                   ;If yes, adjust.
MERIDIAN:      CMP     AX,0                    ;Midnight?
               JNZ     NOT_MIDNIGHT
               MOV     AX,12                   ;If yes, adjust.
NOT_MIDNIGHT:  MOV     CL,0FFH                 ;Suppress leading zeros.
               MOV     CH,":"
               CALL    STORE_WORD              ;Store it.

               MOV     AX,DX                   ;Retrieve time.
               MOV     CL,5                    ;Shift to minutes bits.
               SHR     AX,CL
               AND     AX,111111B              ;Mask off all but minutes.
               XOR     CL,CL
               POP     DX                      ;Retrieve hours.
               MOV     CH,"p"                  ;Assume PM.
               CMP     DX,12                   ;Is it PM?
               JAE     PM
               MOV     CH,"a"                  ;If no, AM.

PM:            CALL    STORE_WORD              ;Store it.
               MOV     SI,OFFSET CR_LF         ;Tack on carriage return
               MOVSW                           ; linefeed.
               MOVSB
               MOV     DX,OFFSET RESULTS       ;Display results.
               MOV     AH,9
               INT     21H
               RET                             ;Done here.

DISPLAY_NAME   ENDP

;----------------------------------------------;
; Converts a two byte hex number to decimal    ;
; and stores the word followed by a delimiter. ;
;                                              ;
; INPUT                                        ;
;   AX = hex number                            ;
;   BL = 10                                    ;
;   CH = delimiter character to store.         ;
;   CL =  0 if zeros are to be stored.         ;
;   CL = -1 if leading zeros ignored.          ;
;   ES:DI points to storage.                   ;
;                                              ;
; OUTPUT                                       ;
;   ES:DI points to next storage location.     ;
;                                              ;
;   AX destroyed.                              ;
;----------------------------------------------;

STORE_WORD     PROC    NEAR

               DIV     BL                      ;Divide by ten.
               ADD     AX,"00"                 ;Convert to ASCII.
               CMP     CL,0                    ;Are we to display leading zero?
               JZ      STORE_IT                ;If yes, store as is.
               CMP     AL,"0"                  ;Is it a leading zero?
               JNZ     STORE_IT                ;If no, store it.
               MOV     AL,SPACE                ;Else, store a space.
STORE_IT:      STOSW
               MOV     AL,CH                   ;Store delimiter character also.
               STOSB
               RET

STORE_WORD     ENDP

;--------------------------------------------------------------------------;
; String storage at end of code to avoid all those zeros in Basic listing. ;
;--------------------------------------------------------------------------;

CURRENT_DIR    LABEL   BYTE
WORKING_DIR    EQU     CURRENT_DIR + 68
RESULTS        EQU     WORKING_DIR + 68

_TEXT          ENDS
               END     START
