title TODIR - Change dir through alias subttl Prologue page 60, 132 comment { ****************************************************************************** File TODIR.ASM Author: Aaron Brenner GEnie mail address A.BRENNER BIX user id albrenner This program is hereby released to the public domain. Purpose: Provide a shorthand for CHDIR. TODIR will read the file TODIR.PTH in either the current directory, on the PATH, or in the directory speci- fied by the TODIRPTH environment variable. TODIR.PTH must be an ASCII file containing shorthand/path pairs, one per line, blank separated. Alias are limited to 12 characters in length, and may contain any printable characters. Syntax: C>TODIR Displays a usage message. C>TODIR Displays all alias/path pairs. C>TODIR Changes the current directory (and current drive, if necessary) to the path corresponding to . Errorlevel set: 0 Path set successfully. 1 Unable to locate TODIR.PTH. 2 Unable to locate alias in TODIR.PTH. 3 No path associated with alias. 4 Unable to change drive/directory to path. 5 No command argument present. 6 Not enough memory Revision history: 1.00 07/15/90 ALB Created. ****************************************************************************** endcomment { subttl Macros page save macro p1,p2,p3,p4,p5,p6,p7,p8,p9 irp y, ifnb push y endif endm restore macro irp z, ifnb pop z endif endm endm endm subttl Program stack and data page todir_stack segment stack dw 128 dup(0) todir_stack ends todir_data segment $buf_size equ 4096 our_env_seg dw 0 ; Pointer to our environment segment our_PSP dw 0 ; Our PSP segment buffer_posn dw $buf_size ; Current position in the buffer buffer_seg dw 0 ; Segment of the file buffer buffer_count dw 0 ; Count of characters in the buffer saved_char dw -1 ; An ungotten character line_buf db 128 dup (0) ; Buffer for a line ;***************************************************************************** ; ; Error messages ; ; Note that the routine that does the output will interpret the following ; control characters: ; ^A output the alias entered on the command line ; ^B output the path associated with the alias ; ;***************************************************************************** usage_msg db 'TODIR v1.00 - Public Domain Software', 13, 10, 13, 10 db 'Usage: TODIR ', 13, 10 db ' or TODIR ?', 13, 10 db ' or TODIR ?', 13, 10, 13, 10 db 'Change drive/directory to the path corresponding to' db ' as set', 13, 10 db 'in TODIR.PTH.', 13, 10 db 'An argument of ? will display all alias/path pairs in' db ' TODIR.PTH.', 13, 10 db 'A followed by ? will display the path' db ' associated with that alias.', 13, 10, '$' all_aliases db 'All aliases in ', 3, ':', 13, 10, 0 no_alias_path db 'No path associated with "', 1, '".', 13, 10, 0 no_alias_fnd db 'Alias "', 1, '" not found.', 13, 10, 0 bad_path db 'Unable to change to "', 2, '".', 13, 10, 0 no_pth_file db 'Unable to locate alias definition file.', 13, 10, '$' no_memory db 'Not enough free memory', 13, 10, '$' crlf_string db 13, 10 command_tail db 127 dup (0) ; Copy of our command tail alias_name db 14 dup (0) ; The alias they entered alias_path db 80 dup (0) ; The path associated with it possible_alias db 14 dup (0) ; A possible one from the file path_file_name db 80 dup (0) ; Where we found TODIR.PTH path_file_hnd dw -1 ; Handle for it path_name_base db 'TODIR.PTH',0 ; Base name of path file $name_base_len = $ - path_name_base ; ; Environment variables to look for ; env_path db 'PATH=' $env_path_len = $ - env_path env_todir db 'TODIRPTH=' $env_todir_len = $ - env_todir env_buffer db 256 dup (0) ; Buffer to hold the env contents todir_data ends subttl Program code page todir_code segment assume cs:todir_code, ds:nothing, es:nothing, ss:todir_stack start proc call initialize ; Set everything up call change_path ; Change to where they want mov ax,4c00h ; Exit to DOS with ERRORLEVEL 0 int 21h ; start endp subttl Program initialization page ;***************************************************************************** ; ; Program initialization ; ;***************************************************************************** initialize proc near mov ax,todir_data ; Set up our data segment mov es,ax ; assume es:todir_data mov es:our_PSP,ds ; Save our PSP segment mov ax,ds:[2ch] ; Get our environment segment mov es:our_env_seg,ax ; Save it mov di,offset command_tail ; Point to our buffer for the cmd tail mov si,81h ; Point to our command tail mov cl,ds:[80h] ; Get the length of the command tail sub ch,ch ; as a word cld ; Make sure of direction rep movsb ; Copy the command tail sub al,al ; Null-terminate it stosb ; push es ; Set our data segment now pop ds ; assume ds:todir_data mov si,offset command_tail ; Point to our copy of the cmd tail mov di,offset alias_name ; Point to alias name buffer mov cx,12 ; Max to copy call copy_string ; Copy it cmp byte ptr alias_name[0],0; Did they enter one? jne init_l2 ; Yep - check for "?" ; ; No command line arg. Just display the usage message and exit 5. ; mov dx,offset usage_msg ; Point to the usage message mov ah,9 ; Display it to console int 21h ; Display the usage message mov ax,4c05h ; Exit with ERRORLEVEL of 5 int 21h ; init_l2: mov bx,offset program_end + 15; Figure out where we end mov cl,4 ; shr bx,cl ; mov ax,cs ; add bx,ax ; sub bx,our_PSP ; Figure out our size push es ; Save this for a sec mov es,our_PSP ; for the SETBLOCK call mov ah,4ah ; Set our allocation int 21h ; pop es ; mov ah,48h ; Now, allocate a file buffer mov bx,$buf_size shr 4 ; Number of paragraphs for the buffer int 21h ; jnc init_l3 ; We got it - continue mov dx,offset no_memory ; Report there ain't enough RAM mov ah,9 ; int 21h ; mov ax,4c06h ; Exit with appropriate ERRORLEVEL int 21h ; init_l3: mov buffer_seg,ax ; Save the returned segment call locate_file ; Get the file cmp word ptr alias_name[0],('?' * 256) + 1; Was it just "?"? jne init_l4 ; No - see if more args ; ; The first command line arg was a "?". We just want to display the entire ; list of alias/path pairs. ; call display_file ; Display the .PTH file mov ax,4c00h ; Pretend we did the change int 21h ; ; init_l4: call skip_spaces ; Skip any more whitespace lodsb ; Get the next byte or al,al ; End of the command line? je init_exit ; Yep - finish up here cmp al,'?' ; Are they querying? jne init_exit ; No - just finish up call match_alias ; Match the alias they entered call display_pair ; Display the alias/path pair mov ax,4c00h ; Pretend we did the change int 21h ; ; init_exit: call match_alias ; Find a match for the alias ret ; Return to Main initialize endp ;***************************************************************************** ; ; Attempt to change the drive/path to that in alias_path. ; ;***************************************************************************** change_path proc near assume ds:todir_data, es:todir_data cmp byte ptr alias_path[0],0; Is there a path there? jne chgp_l1 ; Yes - try to change to it mov si,offset no_alias_path ; Point to error message call display_message ; Spit it out mov ax,4c03h ; Exit with ERRORLEVEL 3 int 21h ; ; chgp_l1: mov dx,offset alias_path[1] ; Point to the path to switch to mov ah,3bh ; DOS fn to change current dir int 21h ; Try to do it jnc chgp_l2 ; It flew - continue mov si,offset bad_path ; Point to error message call display_message ; Show it mov ax,4c04h ; Exit with appropriate ERRORLEVEL int 21h ; ; chgp_l2: mov ax,word ptr alias_path[1]; Get the first 2 bytes of the string cmp ah,':' ; Is there a drive present? jne chgp_exit ; Nope - we're done sub al,'A' ; Make it a disk number mov dl,al ; Put it where DOS wants mov ah,0eh ; Fn to select drive int 21h ; chgp_exit: ret ; Return to Main change_path endp subttl Various utility routines page ;***************************************************************************** ; ; U t i l i t y R o u t i n e s ; ;***************************************************************************** ;***************************************************************************** ; ; Locate the file TODIR.PTH. The search order is: ; 1. In the path specified by the TODIRPTH environment variable. If this ; specifies a directory, the file name is assumed to be TODIR.PTH. ; 2. In a directory specified by the PATH environment variable. ; 3. In the current directory. ; ; Input: ; None. ; ; Output: ; path_file_name is filled in with the file spec, and the handle for ; the file is stored in path_file_handle ; ; Registers: ; All preserved. ; ;***************************************************************************** locate_file proc near assume ds:todir_data, es:todir_data save ax, bx, cx, dx, si, di mov si,offset env_todir ; Point to the "TODIRPTH" var name mov cx,$env_todir_len ; Get the length of it call getenv ; Try to get it cmp byte ptr env_buffer[0],0; Is there a path there? je lctf_on_path ; Nope - look along the path mov si,offset env_buffer ; Copy it into our path mov di,offset path_file_name; mov cx,78 ; call copy_string ; cmp byte ptr [di - 1],'\' ; Is there a path sep? je lctf_l1 ; Yep - just tack on the file name cmp byte ptr [di - 1],'/' ; Check for other path sep je lctf_l1 ; Yep - tack on the file name mov dx,offset path_file_name[1]; mov ax,4300h ; See if it's a file or a dir int 21h ; jc lctf_on_path ; If unable, look along the path test cx,10h ; Is this a directory? jz lctf_l2 ; Nope - use that file name mov al,'\' ; Put in a path separator stosb ; inc path_file_name ; Account for it lctf_l1: mov si,offset path_name_base; Point to the file name mov cx,$name_base_len ; Size of it rep movsb ; Copy to the path (terminates it, too) add path_file_name,$name_base_len - 1; Add to string length lctf_l2: mov dx,offset path_file_name[1]; Get ready to open it mov ax,3d00h ; Open for read-only int 21h ; Try to open that puppy jnc lctf_done ; If we did, save the handle & exit lctf_on_path: mov si,offset env_path ; Point to "PATH=" mov cx,$env_path_len ; Get the length of it call getenv ; Get the value for it cmp env_buffer[0],0 ; Is there a PATH defined? je lctf_curr_dir ; Nope - try current directory ; ; To make things a little easier to deal with, step through the PATH string, ; replacing ";" with " ". ; mov si,offset env_buffer ; Point to the PATH string mov di,si ; Twice lctf_l3: lodsb ; Get a character cmp al,';' ; Is it one we need to change? jne lctf_l4 ; No - store it mov al,' ' ; Replace it with a blank lctf_l4: stosb ; Stuff it back in or al,al ; Hit the end yet? jnz lctf_l3 ; Nope - check the whole thing mov si,offset env_buffer ; Start back at the beginning lctf_l5: mov di,offset path_file_name; Point to the final path name mov cx,65 ; Biggest path allowed by DOS call copy_string ; Copy it in cmp path_file_name[0],0 ; Is there anything there? je lctf_curr_dir ; No - look in the current directory cmp byte ptr [di - 1],'\' ; Is there a path sep? je lctf_l6 ; Yes - just add the file name cmp byte ptr [di - 1],'/' ; Other path sep? je lctf_l6 ; Yep - continue mov al,'\' ; Add a path separator stosb ; inc path_file_name ; Account for it in the length lctf_l6: push si ; Save where we were mov si,offset path_name_base; Point to the actual file name mov cx,$name_base_len ; Size of it rep movsb ; Copy it into the final file spec pop si ; add path_file_name[0],$name_base_len - 1; Account for it mov dx,offset path_file_name[1]; Try to open that baby mov ax,3d00h ; int 21h ; jnc lctf_done ; If it went, save the handle & exit jmp short lctf_l5 ; Not there - try next path lctf_curr_dir: ; ; The file isn't on the path and it isn't in the TODIRPTH path. Try the ; current directory. If it isn't there, report an error. ; mov dx,offset path_name_base; Point to base file name mov ax,3d00h ; Try to open it int 21h ; jnc lctf_done ; No error - save the handle and exit mov dx,offset no_pth_file ; Let 'em know we couldn't find it mov ah,9 ; int 21h ; mov ax,4c01h ; Exit w/ERRORLEVEL of 1 int 21h ; ; lctf_done: mov path_file_hnd,ax ; Save the handle restore ret ; Return to caller locate_file endp ;***************************************************************************** ; ; Retrieve the contents of an environment variable. ; ; Input: ; DS:SI pointer to the name (including the "=") of the var ; CX length of the name (including the "=") ; ; Output: ; env_buffer will be filled with the contents of the variable. If the ; first byte of env_buffer is 0, then the variable wasn't found. Up to ; 255 characters will be copied. ; ; Registers: ; All preserved. ; ;***************************************************************************** getenv proc near assume ds:todir_data, es:todir_data save ax, bx, cx, dx, di, ds mov es,our_env_seg ; Get our environment segment assume es:nothing sub ax,ax ; We'll be scanning for a 0 byte sub di,di ; Start at the beginning of it mov bx,si ; Save the pointer to the name mov dx,cx ; Save its length gtnv_l1: repe cmpsb ; See if we've found it je gtnv_l2 ; Yep - copy the contents mov cx,-1 ; Look forever for the end of this one repne scasb ; Find the end of this var mov si,bx ; Restore the pointer & length mov cx,dx ; cmp byte ptr es:[di],0 ; End of the environment? jne gtnv_l1 ; No - keep looking gtnv_l2: mov si,di ; Get ready to copy from the environment push ds ; Swap segments push es ; pop ds ; pop es ; assume ds:nothing, es:todir_data mov di,offset env_buffer ; Point to the destination mov cx,255 ; Max to copy gtnv_l3: lodsb ; Copy a byte stosb ; or al,al ; Did we just copy the ender? loopnz gtnv_l3 ; Loop if not restore assume ds:todir_data ret ; Return to caller getenv endp ;***************************************************************************** ; ; Display an alias/path pair ; ; Input: ; possible_alias set to the alias to display ; alias_path set to the corresponding path ; ; Output: ; Both are displayed. ; ; Registers: ; All preserved. ; ;***************************************************************************** display_pair proc near save ax, bx, cx, dx, si mov si,offset possible_alias; Display the alias name first mov al,[si] ; Get the length cbw ; as a word call display_string ; Display the alias mov cx,16 ; Use field width of 16 sub cx,ax ; Figure out how many blanks to output mov dl,' ' ; dspp_l1: mov ah,6 ; Output a space int 21h ; loop dspp_l1 ; Loop to fill out field mov si,offset alias_path ; Now, display the associated path call display_string ; mov dx,offset crlf_string ; End this line mov cx,2 ; mov bx,1 ; mov ah,40h ; int 21h ; restore ret ; Return to caller display_pair endp ;***************************************************************************** ; ; Display the entire alias file ; ; Input: ; path_file_hnd handle to read from ; ; Output: ; The file is displayed as a series of alias/path pairs. ; ; Registers: ; All preserved. ; ;***************************************************************************** display_file proc near save si mov si,offset all_aliases ; Display the name of the file call display_message ; dspf_l1: call get_pair ; Get a pair from the file jc dspf_exit ; If EOF, we're done call display_pair ; Display that pair jmp short dspf_l1 ; Loop back 'til EOF dspf_exit: restore ret ; Return to caller display_file endp ;***************************************************************************** ; ; Read an alias/path pair from the file ; ; Input: ; None. ; ; Output: ; CF = 1 EOF has been reached (^Z is recognized as EOF) ; CF = 0: ; possible_alias the alias read from the file ; alias_path the corresponding path ; ; Registers: ; All preserved ; ;***************************************************************************** get_pair proc near save cx, si, di getp_l1: call get_line ; Get a line from the file jc getp_exit ; Exit if EOF cmp line_buf[0],0 ; Empty line? je getp_l1 ; Yep - ignore it mov si,offset line_buf ; Point to the line buffer mov di,offset possible_alias; And to the name buffer mov cx,12 ; Max to copy call copy_string ; Copy the alias name cmp possible_alias[0],0 ; Empty line? je getp_l1 ; Yep - ignore it mov di,offset alias_path ; Point to the path buffer mov cx,65 ; Max to copy call copy_string ; Copy to the aliased path clc ; Make sure we return success getp_exit: restore ret ; Return to caller get_pair endp ;***************************************************************************** ; ; Get a line of text from the path file ; ; Input: ; None. ; ; Output: ; CF = 1 EOF has been reached. ; CF = 0: ; line_buf is set to the next line from the file. All alphas are ; folded to upper case. ; ; Registers: ; All preserved. ; ;***************************************************************************** get_line proc near assume ds:todir_data, es:todir_data save ax, cx, di mov di,offset line_buf ; Point to our line buffer mov cx,127 ; Max to store getl_l1: call get_char ; Get a character from the file jz getl_EOF ; Exit if EOF cmp al,13 ; Is it a CR? je getl_l2 ; Yep - check for LF following cmp al,10 ; Is it a LF? je getl_l3 ; Yep - check for CR following jcxz getl_l1 ; Ignore it if the buffer's full call casetize ; Make it upper case stosb ; Stuff it in dec cx ; Knock it off the count jmp short getl_l1 ; Loop back for more getl_l2: call get_char ; Get the NEXT character jz getl_eof ; Stop if EOF cmp al,10 ; Is it the LF following a CR? je getl_exit ; Yep - we're done with this line mov ah,1 ; mov saved_char,ax ; Save it for next time jmp short getl_exit1 ; Exit now getl_l3: call get_char ; Get the NEXT character jz getl_eof ; Stop if EOF cmp al,13 ; Is it the CR following a LF? je getl_exit ; Yep - we're done with this line mov ah,1 ; mov saved_char,ax ; Save it for next time jmp short getl_exit1 ; Exit now getl_EOF: ; ; We get here when get_char reports we've reached EOF. We only want to return ; EOF when the line's empty. ; cmp di,offset line_buf[1] ; Are we at the beginning of the buf? jmp short getl_exit ; If we are, CF will be 1 getl_exit1: clc ; Make sure we don't report EOF getl_exit: mov byte ptr [di],0 ; Terminate the line buffer restore ret ; Return to caller get_line endp ;***************************************************************************** ; ; Attempt to match the alias from the command line with one from the file. ; ; Input: ; alias_name set to the alias to look for ; ; Output: ; alias_path set to the corresponding path ; ; Registers: ; All preserved. ; ;***************************************************************************** match_alias proc near save cx, si, di mov ch,0 ; Make sure high byte is clear mtch_l1: call get_pair ; Get an alias/path pair jc mtch_err ; Oops - if EOF, no matches mov cl,alias_name[0] ; Get length of our alias inc cl ; Allow for length byte mov si,offset alias_name ; Point to the one they entered mov di,offset possible_alias; Point to the one from the file repe cmpsb ; See if they match jnz mtch_l1 ; Nope - keep trying restore ret ; Return to caller ; mtch_err: ; ; We get here if we hit EOF - that means that there is no possible match for ; the given alias. ; mov si,offset no_alias_fnd ; Let 'em know it ain't there call display_message ; mov ax,4c02h ; Exit with appropriate ERRORLEVEL int 21h ; match_alias endp ;***************************************************************************** ; ; Get the next character from the file. ; ; Input: ; buffer_seg segment of file data buffer ; buffer_posn current position the buffer ; buffer_count number of characters in the buffer ; ; Output: ; ZF = 1 EOF has been reached ; ZF = 0: ; AL next character. ; ; Registers: ; All but AX preserved. ; ;***************************************************************************** get_char proc near assume ds:todir_data, es:todir_data save si, es sub ax,ax ; See if there was a saved character dec ax ; xchg ax,saved_char ; cmp ax,-1 ; je getc_l1 ; Nope - read the next one in or ax,ax ; Make sure and clear ZF jmp short getc_exit ; Exit now getc_l1: cmp buffer_count,0 ; Is the buffer empty? jne getc_l2 ; Nope - read the next byte from it call fill_buffer ; jz getc_exit ; EOF - return it getc_l2: les si,dword ptr buffer_posn; Point at the next available byte assume es:nothing lods byte ptr es:[si] ; Get it from the buffer cmp al,1ah ; Is it the fake EOF? je getc_exit ; Yep - exit with ZF set dec buffer_count ; Knock it off the count mov buffer_posn,si ; Save updated buffer position or si,si ; Clear ZF for return getc_exit: restore assume es:todir_data ret ; Return to caller get_char endp ;***************************************************************************** ; ; Fill the buffer from the file. ; ; Input: ; path_file_hnd handle to read from ; ; Output: ; ZF = 1 EOF has been reached ; ZF = 0: ; buffer_posn set to beginning of buffer ; buffer_count set to the number of bytes actually read ; ; Registers: ; All preserved. ; ;***************************************************************************** fill_buffer proc near assume ds:todir_data, es:todir_data save ax, bx, cx, dx mov bx,path_file_hnd ; Get the handle mov cx,$buf_size ; Number of bytes to try to read sub dx,dx ; Start at 0 in the buffer push ds ; Save our seg for a sec mov ds,buffer_seg ; Get the segment for the buffer mov ah,3fh ; DOS fn to read int 21h ; Try to read from the file pop ds ; Get our segment back jnc filb_l1 ; If no error, reset pointer & count sub ax,ax ; Act like we hit EOF filb_l1: mov buffer_count,ax ; Save how many we read mov buffer_posn,0 ; Reset to start of buffer or ax,ax ; If we hit EOF, set ZF filb_exit: restore ret ; Return to caller fill_buffer endp ;***************************************************************************** ; ; Skip spaces in a string. ; ; Input: ; DS:SI pointer to string ; ; Output: ; DS:SI pointer to first non-blank ; ; Registers: ; All but SI preserved. ; ;***************************************************************************** skip_spaces proc near save ax sksp_l1: lodsb ; Get a character cmp al,' ' ; Is it a space? je sksp_l1 ; Yep - skip it cmp al,9 ; Is it a tab? je sksp_l1 ; Yep - skip it dec si ; Point back to it restore ret ; Return to caller skip_spaces endp ;***************************************************************************** ; ; Copy a string, making it upper case. ; ; Input: ; DS:SI pointer to source buffer. May have leading whitespace, ; and is assumed to be nul-terminated. ; ES:DI pointer to dest buffer. ; CX maximum characters to copy ; ; Output: ; First byte of buffer at DI will be set to the length copied, and all ; alphas are folded to upper case. SI will point to the character just ; *after* the last character that was copied, and DI will point to a ; nul byte at the end of the string. ; ; Registers: ; All but SI and DI preserved. ; ;***************************************************************************** copy_string proc near assume ds:todir_data, es:todir_data save ax, bx, cx mov byte ptr es:[di],0 ; Clear the dest length call skip_spaces ; Skip any whitespace mov bx,di ; Point to the length byte inc di ; Point to the first available byte cpys_l1: lodsb ; Get a byte or al,al ; End of it? je cpys_exit ; Yep - exit now cmp al,' ' ; Whitespace? je cpys_exit ; Yep - exit cmp al,9 ; Whitespace? je cpys_exit ; Yep - exit jcxz cpys_l1 ; If the buffer's full, ignore it call casetize ; Make it upper case stosb ; Store it inc byte ptr [bx] ; Count it dec cx ; jmp short cpys_l1 ; Do the next one cpys_exit: sub al,al ; Make sure it's also nul-terminated stosb ; dec si ; Point 'em back to the stopping points dec di ; restore ret ; Return to caller copy_string endp ;***************************************************************************** ; ; Fold a character to upper case. ; ; Input: ; AL character to convert ; ; Output: ; AL converted character ; ; Registers: ; All but AL preserved. ; ;***************************************************************************** casetize proc near cmp al,'a' ; Is it lower case? jb cstz_exit ; Nope - exit cmp al,'z' ; Are you sure? ja cstz_exit ; Yep - never mind xor al,20h ; Make it upper case cstz_exit: ret ; Return to caller casetize endp ;***************************************************************************** ; ; Display a message, allowing for expansion of special control characters. ; ; Input: ; DS:SI pointer to message to display. ; ; Output: ; The message is displayed on the console. ; The following characters in the message will be treated specially: ; ^A (01h) causes the alias name to be displayed ; ^B (02h) causes the associated path to be displayed ; ^C (03h) causes the alias file name to be displayed ; ; Registers: ; All preserved. ; ;***************************************************************************** display_message proc near assume ds:todir_data, es:todir_data save ax, dx, si dspm_l1: lodsb ; Get a byte or al,al ; Is it the end? jz dspm_exit ; Yep - we're done cmp al,1 ; Need to display the alias? jne dspm_l2 ; Nope - check for the path push si ; Save where we are mov si,offset alias_name ; Point to the alias name call display_string ; Display the alias pop si ; Get our position back jmp short dspm_l1 ; Loop back dspm_l2: cmp al,2 ; Need to display the path? jne dspm_l3 ; No - check for alias file name push si ; Save where we are mov si,offset alias_path ; Point to the path call display_string ; Display the path pop si ; Get our position back jmp short dspm_l1 ; Loop back dspm_l3: cmp al,3 ; Need to display the alias file path? jne dspm_l4 ; No - display this character push si ; Save where we are mov si,offset path_file_name; Point to the file name call display_string ; Display it pop si ; Get our position back jmp short dspm_l1 dspm_l4: mov dl,al ; Put it where DOS wants mov ah,6 ; Direct I/O function int 21h ; Display the character jmp short dspm_l1 ; Loop back dspm_exit: restore ret ; Return to caller display_message endp ;***************************************************************************** ; ; Display a length-prefixed string. ; ; Input: ; DS:SI pointer to the string to display ; ; Output: ; The string is output to stdout. ; ; Registers: ; All preserved. ; ;***************************************************************************** display_string proc near assume ds:todir_data, es:todir_data save ax, bx, cx, dx, si mov ah,40h ; Write the string mov bx,1 ; to stdout mov cl,[si] ; Get the length byte mov ch,0 ; Make that a word mov dx,si ; Get pointer to buffer inc dx ; Skip the length byte int 21h ; Display the string restore ret ; Return to caller display_string endp program_end label byte todir_code ends end start