home *** CD-ROM | disk | FTP | other *** search
- ;************************* PUSHD.ASM *************************************
- ;
- ; PUSHD.ASM version 1.2
- ;
- ; Usage:
- ; PUSHD directory
- ; Will push the current directory onto the directory stack
- ; if there is a location available and changes to the current
- ; directory to the specified parameter.
- ; PUSHD
- ; Will change the current directory to the directory stored
- ; in the top of the stack and will place the current directory
- ; on the top of the stack.
- ; PUSHD +n
- ; Will change the current directory to the directory stored
- ; in stack location n, with 1 being the bottom of the stack
- ; and 6 being the top. The stack will be compressed to remove
- ; any empty space and the current directory will be stored
- ; on top of the stack.
- ; Purpose: This program will store directories in a memory-resident
- ; area and change to a specified directory, so that the
- ; user may switch back to a previous directory without having
- ; to either know or to type in the required directory. If the
- ; program terminates abnormally an error message will be
- ; printed to the standard error.
- ; Preconditions:
- ; (The first seven conditions are required for functionality
- ; with POPD and DIRS.)
- ; 1) PUSHD must be hooked to interrupt 13.
- ; 2) PUSHD must have the same commands from beginning
- ; to after definition of push6d, so that it knows how
- ; to access the resident code of PUSHD. (This includes
- ; the fact that there are 6 locations for directory storage
- ; which are 67 bytes in size.)
- ; 3) PUSHD must have the signature "PUSHD VERSION 1.1".
- ; 4) PUSHD must look for 7788 in ax and 7789 in bx for
- ; a call to int 13.
- ; 5) PUSHD must put the value of 7789 into ax and 7788
- ; into bx upon calling int 13 by DIRS, if PUSHD is installed.
- ; 6) PUSHD will set the data segment to be equal to the data
- ; segment that PUSHD used to install itself.
- ; 7) DS:[nextpush] (DS of PUSHD installation) must hold
- ; the location of the next empty directory stack location.
- ; 8) For the last two usages PUSHD must already be installed,
- ; otherwise an error condition is generated.
- ; 9) Enough memory space must be available for the directory
- ; stack and other resident code (new interrupt, etc.)
- ; Postconditions:
- ; 1) An appropriate error message will be printed OR
- ; 2) The parameter directory will become the current directory
- ; and the current directory will be saved on the stack (usage
- ; #1), with DS:[nextpush] being incremented to the next
- ; storage position OR
- ; 3) The directory on the top of the stack will become the
- ; current directory and the current directory will be placed
- ; in the top position on the stack (usage #2) OR
- ; 4) The directory stored in location "n" (starting with 1 as
- ; the bottom and six as the top) will become the current
- ; directory with the contents of the stack storage above the
- ; the targeted directory shifting downward one to effectively
- ; eliminate the "gap" left by the targeted directory. Also,
- ; the current directory will be placed on top of the directory
- ; stack (usage #3)
- ; 5) If PUSHD was not previously loaded into memory, due to
- ; not use or abnormal termination, the program will now be
- ; loaded with a reduction of memory of 1024 bytes. This
- ; includes the storage space required for the stack and
- ; the new interrupt 13 handler.
- ; 6) An error code will be generated.
- ; Error Codes:
- ; 0) Successful completion.
- ; 249) Error popping directory off stack.
- ; 250) Error pushing current directory.
- ; 251) Directory Stack is full.
- ; 252) Error changing to directory given on command line.
- ; 253) Command Line parameter exceeds Directory Stack depth.
- ; 254) Illegal Characters on the Command Line.
- ; 255) Command Line parameter not in valid directory range (1-6).
- ; Version changes:
- ; PUSHD v. 1.2: July 21, 1990.
- ; coded in Toad Hall tweaks and suggestions (much
- ; thanks to David Kirschbaum).
- ; PUSHD v. 1.1: July 14, 1990.
- ; added "+n" option.
- ; added change to parameter option.
- ; changed no parameter option to switch current and
- ; top directories.
- ; changed hooked interrupt to 13 from 16.
- ; added error codes for abnormal termination.
- ; changed writes from vector 9 to vector 40h of
- ; int 21h.
- ; changed program termination from int 20h to vector
- ; 4Cxxh int 21h, where xx represents the error code
- ; generated.
- ; removed stack wrap around.
- ; PUSHDIR v. 1.0: Copyright 1986, Ziff-Davis Publishing Co.
- ; From PC Magazine, May 27, 1986
- ; No changes.
- ; Future Enhancements:
- ; 1) Change the "n" parameters so that it refers to the
- ; top of the stack, not the bottom (RELATIVE from the top
- ; NOT ABSOLUTE from the bottom).
- ; 2) Make program an .EXE file.
- ; 3) Remove extra push/pop commands.
- ; 4) Fix up various hacks.
- ; 5) Correct error caused by 3 or more blanks at end of
- ; command line tail.
- ; 6) Add a help option, ?, from the command line.
- ; 7) have "signature" loaded into memory so that programs such
- ; as "POPDROP" can identify the stack as resident.
- ;
- ; Created by:
- ; (from ideas based in UNIX and from PC Magazine's POPDIR.COM)
- ; William P. Sarra
- ; CIS:71041,347
- ; arpa: sarra@TOPAZ.RUTGERS.EDU
- ; uucp: ...{ames,cbosgd, harvard, moss}!rutgers!topaz.rutgers.edu!sarra
- ;
- ;*****************************************************************************
-
-
- MAIN group CSEG
- CSEG segment public para 'code'
- assume CS:MAIN,DS:MAIN,ES:MAIN,SS:MAIN
-
- org 2CH ;v1.2
- envseg label word ;Environment Segment in PSP v1.2
-
- org 80h
- cmd_line label byte
-
- org 100h ;.COM file
-
- Begin: jmp Start ;program starts here
-
- signature db 'PUSHD VERSION 1.1'
- SIG_LEN equ $-signature
-
- savedint13 dd ? ;old int 13h vector
-
- nextpush dw offset MAIN:push1d ;next place to save a dir
-
- push1d db 67 dup (0) ;storage for a saved dir
- push2d db 67 dup (0) ;more storage
- push3d db 67 dup (0) ;more storage
- push4d db 67 dup (0) ;more storage
- push5d db 67 dup (0) ;more storage
- push6d db 67 dup (0) ;last storage
-
- ;up to here must be EXACTLY identical in PUSHD, POPD, and DIRS so that
- ;POPD and DIRS can know how to access the memory space reserved by the first
- ;PUSHD.
-
- ;**************************************************************************
- ;
- ; PROCEDURE: MYINT13
- ;
- ; Purpose: myint13 is an interrupt handler chained onto the existing
- ; interrupt handler. It is used to find out if PUSHD is
- ; already installed and if it is, where it located. It works
- ; by adding another function to int 13h. To use it ax = 7788h,
- ; bx = 7789h, and DS:si points to the signature string. If any
- ; one of these conditions are not true, then the int 13h call
- ; is passed onto the old routine without doing anything. If
- ; they are all true, then we switch ax and bx and return DS =
- ; code segment (CS) of the interrupt handler.
- ; Preconditions:
- ; For a check to see if PUSHD is installed, ax = 7788h and bx
- ; = 7789h DS:si points to the string "PUSHD VERSION 1.1".
- ; Postconditons:
- ; If PUSHD is installed, ax = 7789h and bx = 7788h, DS = CS of
- ; the interrupt handler.
- ; If PUSHD was not installed, a new function is added to
- ; interrupt 13h which is checked before any other functions.
- ;
- ;****************************************************************************
-
- myint13 proc far
-
- pushf ;save flags
- cmp ax,7788h ;possible signature request ?
- je CHECKSIG ;yes
- NOTSIG:
- popf ;no - recover flags
- jmp CS:[savedint13] ;go to old routine as normal
-
- CHECKSIG:
- cmp bx,7789h ;possible signature request ?
- jne NOTSIG ;no
-
- ;ax and bx were correct for a signature request.
- ;Now see if DS:si was pointing to the signature string.
- ;Signature string MUST be unique from any other programs.
-
- push ES ;save the registers we will use
- push di
- push cx
- mov di,offset main:signature ;address of the signature
- mov cx,sig_len ;length of the signature
- repe cmpsb ;does string at DS:si match ES:di ?
- pop cx ;recover all registers we used
- pop di
- pop ES
- jne NOTSIG ;no, not correct signature
-
- ;Signature request: return DS equal to the current code segment so
- ; subsequent PUSHD's, POPD's and DIRS know where the original
- ; is located.
-
- push CS
- pop DS ;set DS = CS
- xchg ax,bx ;flip these two so we know that
- ;DS is being returned
- popf ;recover original flags
- iret ;return back to the program
- ;that called the int 13h
-
- myint13 endp
-
- ENDRESIDENT label byte
- ;ENDRESIDENT EQU (OFFSET CSEG - $) + 0FH ;v1.2
-
- ;code after here will not remain resident
-
-
- ;**********************************************************************
- ;
- ; PROCEDURE: Push_Dir
- ;
- ; Purpose: This procedure will put the current directory into
- ; the storage location specified si. It will store
- ; the whole path to the current directory and will add
- ; the drive and root specification as well.
- ; Preconditions:
- ; DS = segment of the storage pointed to by si.
- ; si points to the storage location.
- ; The storage location is 67 bytes wide.
- ; The error message "abortmsg" is defined and it's length
- ; has been determined.
- ; Postconditions:
- ; si will be three more than the si passed into the
- ; procedure.
- ; si - 3 will point to beginning of the current directory,
- ; starting with the drive specification.
- ; OR an error message will be generated on stderr and the
- ; program will terminate with an error code.
- ;
- ;**************************************************************************
-
- Push_Dir proc
-
- ;DS = segment of the directory storage in si
-
- ASSUME DS:CSEG ;assume TSR v1.2
-
- ;store the current directory, including disk drive letter
-
- add si,3
- xor dl,dl ;default drive v1.2
- mov ah,47h ;dos function number
- int 21h ;get current directory
- sub si,3
- jc ABORTERR ;error message if carry set
-
- mov ah,19h ;dos function number
- int 21h ;get the current drive
- add al,'A' ;convert to ascii
- mov [si],al ;add the "D:\" in front of path v1.2
- mov word ptr [SI+1],'\:' ;type them in backwards.. v1.2
- ret
-
- ABORTERR:
-
- ;error in getting current directory -- generate error message
- ; and exit with an error code
-
- mov dx,offset MAIN:abortmsg ;address of error message
- mov cx,ABORTMSG_LN
-
- mov al,0FAH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
- Push_Dir endp
-
-
- ;********************************************************************
- ;
- ; PROCEDURE: Pop_Dir
- ;
- ; Purpose: This procedure will change the current directory to
- ; the one specified in the location pointed to by
- ; bp. It will also change the current drive specification,
- ; if necessary.
- ; Preconditions:
- ; bp points to the location of the directory to change to.
- ; ES is equal to the segment that holds the targeted
- ; directory.
- ; The error message "errpop1" is defined and it's length
- ; has been determined.
- ; Postconditions:
- ; The current drive and directory are those specified in
- ; in the parameter pointed to by bp, if valid.
- ; Otherwise, an error message is printed and a specific
- ; error code is generated.
- ;
- ;**************************************************************************
-
- Pop_Dir proc
-
- ;bp holds location of directory to pop off stack
-
- ;set the current directory
-
- mov dx,bp ;load DS:dx with directory to set
- mov ah,3bh ;dos function number
- int 21h ;set current dir back
- jc ERRPOP ;branch on error
-
- mov dl,DS:[bp] ;v1.2
- sub dl,'A' ;convert to binary (0=A, 1=B)
- mov ah,0eh ;dos function number
- int 21h ;set drive
- jc ERRPOP
-
- ret
-
- ERRPOP:
-
- ;Error in changing to the desired directory -- print an
- ; error message and exit with error code.
-
- mov dx,offset MAIN:errpop1 ;error message
- mov cx,ERRPOP1_LN
- mov al,0F9H ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
- Pop_Dir endp
-
-
- ;*****************************************************************
- ;
- ; DATA SECTION
- ;
- ;*****************************************************************
-
- install db 1 ;0 = already installed, 1 = not installed
-
- abortmsg db 'Error reading the directory.',13,10
- ABORTMSG_LN equ $-abortmsg
- installmsg db 'PUSHD installed.'
- INSTALLMSG_LN equ $-installmsg
-
- in_dir_msg db 'Valid Directories range between 1 and 6.',13,10
- IN_DIR_MSG_LN equ $-in_dir_msg
- bs_online db 'Invalid Command Line Parameters.',13,10
- BS_ONLINE_LN equ $-bs_online
- not_pushed db 'Parameter exceeds Directory Stack depth.',13,10
- NOT_PUSHED_LN equ $-not_pushed
- full_stack db 'Cannot push Directory -- STACK FULL.',13,10
- FULL_STACK_LN equ $-full_stack
- errpop1 db 'Error popping requested directory.',13,10
- ERRPOP1_LN equ $-errpop1
-
- BLANK equ 20h ;' '
- DELIMITER equ 2Bh ;'+'
- UP_LIMIT equ 36h ;'6'
- LOW_LIMIT equ 31h ;'1'
-
- DRIVE_DELIM equ 3Ah ;':'
-
- params db ? ;Command line tail
- params_ln dw ? ;Length of command line tail
- targ_dir dw ? ;location of storage of targeted directory
-
- temp_dir db 67 dup (0) ;temporaray directory storage
-
- ;***********************************************************************
- ;
- ; CODE STARTS
- ;
- ;***********************************************************************
-
- Start:
-
- ;get command line tail
-
- cld
-
- ;v1.2 I entirely rewrote this section. What a kludge!
-
- mov si,offset cmd_line ;command line tail
- lodsb ;snarf length byte, bump SI
-
- ;SI -> first char (probably a space!)
-
- xor ah,ah ;clear msb
- mov cx,ax ;into CX
- mov params_ln,ax ;save for later
- push ax ;save length on stack for later
- jcxz INST_CHK ;CX is 0, branch
-
- ;We have a non-null command line
-
- mov di,offset MAIN:params ;store since it may get
- rep movsb ;destroyed
-
- INST_CHK:
-
- ;first check to see if PUSHD is already installed
-
- mov ax,7788h ;signature request
- mov bx,7789h ;signature request
- mov si,offset main:signature ;point to signature
- int 13h ;is it installed ?
-
- ASSUME DS:CSEG ;assume TSR's DS v1.2
-
- cmp bx,7788h ;were ax and bx switched ?
- jne NOTINSTALLED ;no
- cmp ax,7789h ;were ax and bx switched ?
- jne NOTINSTALLED ;no
-
- ;yes it is installed already
-
- mov CS:[install],0 ;don't install it again
-
- NOTINSTALLED:
-
- ; check for command line parameters
-
- pop cx ;get saved cx
- push DS ;store current DS
-
- mov ax,CS ;v1.2
- mov DS,ax ;v1.2
- ASSUME DS:MAIN ;reminder v1.2
-
- or cx,cx ;check for no parameters
- jnz ERR1 ;no parameters
- jmp CHK_STACK
-
- ERR1: mov di,offset MAIN:params
- mov al,BLANK ;remove leading blanks
- repe scasb
- dec di
- inc cx
- mov si,di ;save position
- lodsb ;snarf first char, bump SI v1.2
- cmp al,BLANK ;space? v1.2
- jne ERR2
- jmp CHK_STACK ;only blanks on tail
-
- ERR2:
- cmp al,DELIMITER ;is it '+' delimiter? v1.2
- je CHK_VALUE
- jmp CHK_STACK_DIR ;directory on command line
-
-
- CHK_VALUE:
-
- ;check parameter values
-
- dec cx ;decr for last LODSB
-
- ;v1.2 Recoded
- lodsb ;snarf digit after '+', bump SI
- cmp al,UP_LIMIT ;above '6'?
- ja INVALID_DIR ;yep, bogus
- cmp al,LOW_LIMIT ;below '1'?'
- jnb FINISH_CHK ;nope, in range ['1'..'6']
-
-
- INVALID_DIR:
-
- ;Invalid directory number -- print error message and exit
- ; with error code
-
- mov dx,offset MAIN:in_dir_msg ;error message
- mov cx,IN_DIR_MSG_LN
- mov al,0FFH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
- FINISH_CHK:
-
- ;check for illegal characters on the command line
-
- dec cx ;decr cmdline count for digit v1.2
- jcxz VALID_DIR
-
- mov ah,al ;save digit v1.2
- mov al,BLANK ;check for following nonblank
- repne scasb ;characters
- mov al,ah ;replace digit v1.2
-
- jcxz VALID_DIR
-
- ;illegal characters found on the command line -- print error
- ; message and exit with and error code
-
- mov dx,offset MAIN:bs_online ;error message
- mov cx,BS_ONLINE_LN
- mov al,0FEH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
-
- VALID_DIR:
-
- ;get targeted pushed directory location
-
- xor ah,ah ;clear ah v1.2
- mov cx,67 ;multiplier v1.2
- sub al,'1' ;'0'..'5' range
- mul cx ;directory offset v1.2
- add ax,offset MAIN:push1d ;base directory buffer v1.2
- mov targ_dir,ax ;save it v1.2
-
- ;check for validly pushed directory
-
- ;CONDITIONS coming into here:
- ; DS = CS = ES = SS
- ; DS (installed) on stack
-
- pop ax ;TSR's CSEG v1.2
- mov DS,ax ;load DS v1.2
- mov ES,ax ;and ES v1.2
- ASSUME DS:CSEG,ES:CSEG ;assume TSR's v1.2
-
- mov bp,DS:[nextpush]
- sub bp,67 ;get top of stack location
-
- cmp bp,CS:[targ_dir] ;make sure directory stack
- jge PROCESS_DIRS ;is deep enough for params
-
- ;The directory stack is not deep enough for the specified command
- ; line parameter -- print an error message and exit with error code
-
- mov dx,offset MAIN:not_pushed ;error message
- mov cx,NOT_PUSHED_LN
- mov al,0FDH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
- PROCESS_DIRS:
-
- ;We have got a valid target directory here, now check to see
- ; if we are working with the top of the stack.
-
- jne NOT_TOP
- push DS ;put DS (installation) on stack
- jmp SHORT NEW_CHK_STACK
-
- CHK_STACK:
-
- ;CONDITIONS coming into here:
- ;coming from no parameters section of parameter check (NOTINSTALLED)
- ;CS = DS = SS = ES, DS (installation) on stack
-
- pop DS ;set ES = DS = DS (installation)
- mov ax,DS ;v1.2
- mov ES,ax ;v1.2
- ASSUME DS:CSEG,ES:CSEG ;reminder v1.2
-
- push DS ;put DS (installation) on stack
- mov bp,DS:[nextpush]
- sub bp,67 ;set bp to be top of the stack
-
- NEW_CHK_STACK: ;common code here v1.2
- mov ax,CS ;v1.2
- mov DS,ax ;v1.2
-
- ;CONDITIONS coming into here:
- ; from PROCESS_DIRS and from fall-through of CHK_STACK
- ; ES = DS (installation), DS = CS = SS, DS (installation) on stack
-
- ;handle the pushing and popping of directories on and off of the
- ; top of the stack
-
- mov si,offset MAIN:temp_dir
- call Push_Dir ;store current dir in temp_dir
- pop DS
- ASSUME DS:CSEG ;assume TSR v1.2
-
- call Pop_Dir ;pop directory in bp
- push DS
- mov ax,CS ;v1.2
- mov DS,ax ;v1.2
- ASSUME DS:MAIN ;reminder v1.2
-
- mov di,bp ;copy temp_dir into top of stack
- mov cx,67 ;stack position
- rep movsb
- mov ES,ax ;AX is still CSEG from above v1.2
- jmp GOTNEXTPUSH
-
- NOT_TOP:
-
- ;CONDITIONS coming into here:
- ;DS = ES = installation DS, CS = SS, nothing on stack
-
- push DS ;store DS
- mov ax,CS ;v1.2
- mov DS,ax ;v1.2
- ASSUME DS:MAIN ;reminder v1.2
-
- mov si,offset MAIN:temp_dir
- call Push_Dir ;store current dir in temp_dir
- mov bp,targ_dir
- pop DS
- ASSUME DS:CSEG ;probably TSR's v1.2
-
- call Pop_Dir ;pop targeted directory
- mov dx,DS:[nextpush]
-
- mov ax,67 ;handy constant v1.2
- sub dx,ax ;67 ;set dx to point to top of stack v1.2
- mov bx,CS:[targ_dir] ;handle variable here v1.2
-
- STACK_LOOP:
-
- ;loop through the directory stack, shifting the the directories
- ; downward to eliminate the space left by popping a directory
- ; in the middle of the stack.
-
- add bp,ax ;v1.2
- cmp bp,dx
- je LAST_DIR ;found the last directory
- mov si,bp ;copy contents pointed to by bp
- mov di,bx ;to targ_dir v1.2
- mov cx,ax ;v1.2
- rep movsb
- add bx,ax ;targ_dir,67 v1.2
- jmp SHORT STACK_LOOP ;continue
-
- LAST_DIR:
-
- ;process last directory on stack
-
- mov si,bp ;otherwise simply copy
- mov di,bx ;curr_dir v1.2
- mov cx,ax ;67 v1.2
- rep movsb
- mov targ_dir,bx ;update v1.2
-
- mov di,bp ;copy temp_dir to top of stack
- mov bx,CS ;v1.2
- mov DS,bx ;v1.2
- ASSUME DS:MAIN ;v1.2
-
- mov si,offset MAIN:temp_dir
- mov cx,ax ;67 v1.2
- rep movsb
- mov ES,bx ;BX is still CSEG from above v1.2
- jmp SHORT GOTNEXTPUSH
-
- CHK_STACK_DIR:
-
- ;push current directory and change to parameter directory
-
- ;CONDITIONS upon entering here:
- ;CS = DS = ES = SS, DS (installed) on stack
-
- pop DS
- ASSUME DS:CSEG ;assume TSR's v1.2
-
- cmp DS:[nextpush],offset MAIN:push6d ;check for full stack
- jg STACK_FULL
- mov si,DS:[nextpush]
- call Push_Dir ;push current onto stack
- push DS
- mov ax,CS ;v1.2
- mov DS,ax ;v1.2
- ASSUME DS:MAIN ;reminder v1.2
-
- mov bp,1 + offset MAIN:params ;one after blank space
-
- ;change to specified directory
-
- mov dx,bp ;load DS:dx with directory to set
- mov ah,3bh ;dos function number
- int 21h ;set current dir back
- jc POP_ERR
-
- ;check and set default drive
-
- mov cx,[params_ln] ;parameter length v1.2
- cmp cx,3 ;if cmdline is less than 3 v1.2
- jb NO_DRIVE ;can't have drive spec D:\ v1.2
-
- cmp byte ptr DS:[bp+1],DRIVE_DELIM ;drive spec? v1.2
- jne NO_DRIVE
-
- mov al,DS:[bp] ;v1.2
- sub al,'A' ;convert to binary (0=A, 1=B) v1.2
- cmp al,1Ah ;'26' == Z as last drive v1.2
- jle ACTION
- sub al,20h ;conversion for lower case drive spec
- ;v1.2
- ACTION:
- mov dl,al ;NOW put it in DL v1.2
- mov ah,0eh ;dos function number
- int 21h ;set drive
- jc POP_ERR
- NO_DRIVE:
- jmp SHORT OK_DIR
-
- POP_ERR:
-
- ;Error occcurred while trying to change to specified directory
- ; print error message and exit with error.
-
- mov dx,offset MAIN:errpop1
- mov cx,ERRPOP1_LN
- mov al,0FCH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
- OK_DIR:
-
- ;Increment the location of the nextpush and set DS as
- ; required by section GOTNEXTPUSH.
-
- pop DS
- add DS:[nextpush],67
- mov ax,CS ;v1.2
- mov DS,ax ;v1.2
- ASSUME DS:MAIN ;reminder v1.2
-
- jmp SHORT GOTNEXTPUSH
-
- STACK_FULL:
-
- ;The directory stack is full -- print error message and
- ; exit with error.
-
- mov dx,offset MAIN:full_stack ;error message
- mov cx,FULL_STACK_LN
- mov al,0FBH ;ERRORLEVEL v1.2
- jmp Msg_Term ;display, terminate v1.2
-
-
- GOTNEXTPUSH:
-
- ;CONDITIONS coming into this section:
- ; CS = DS = SS = ES
- ASSUME DS:MAIN,ES:MAIN ;reminder v1.2
-
- cmp [install],1 ;should we install it v1.2
- je DOINSTALL ;yes
-
- ;PUSHD is already installed, exit successfully.
-
- mov ax,4c00h
- int 21h ;no, we are done
-
-
- DOINSTALL:
-
- ;PUSHD is not installed, install it by making part of it
- ; memory resident.
-
- assume DS:MAIN
-
- ;Save the current int 13h vector.
-
- mov ax,3513h ;dos function 35h, vector 13h
- int 21h ;get the existing vector into ES:bx
- mov word ptr [savedint13],bx ;save ES:bx
- mov word ptr [savedint13+2],ES ;save ES:bx
-
- ;Set the new int 13h vector to point to routine myint13.
-
- mov dx,offset MAIN:myint13 ;point to new routine
- mov ax,2513h ;dos function 25h, vector 13h
- int 21h ;set new vector to DS:dx
-
- ;Show an installation message on the screen.
- ; This message can be suppressed by redirecting output to NUL.
-
- mov dx,offset MAIN:installmsg
- mov cx,INSTALLMSG_LN
- mov bx,1 ;write to stdout
- mov ah,40h
- int 21h ;show installation message
-
- ;Free up the memory occupied by the envirnoment so it is not
- ; permanently wasted.
-
- mov ES,envseg ;load ES with env seg v1.2
- mov ah,49h ;dos function number
- int 21h ;free the environment memory
-
- ;Terminate resident protecting only the first part of this program.
-
- ;v1.2 Let the compiler do the computing!
-
- mov dx,offset MAIN:ENDRESIDENT
- add dx,0FH
- mov cl,4
- shr dx,cl
- ; mov dx,ENDRESIDENT / 16 ;resident code in paragraphs v1.2
- mov ax,3100h ;dos function 31h, error code=0
- int 21h ;terminate and remain resident
-
-
-
- ;*********************************************************************
- ;
- ; PROCEDURE: Msg_Term
- ;
- ; Purpose: This procedure will handle the printing of error messages
- ; and termination with the correct errorlevel.
- ; Preconditions:
- ; DX = error message address.
- ; CX = error message length.
- ; AL = ERRORLEVEL.
- ; Postconditions:
- ; The program will be terminated with the appropriate
- ; error message printed on standard error and with the
- ; the errorlevel stored in al.
- ;
- ;***************************************************************************
-
- Msg_Term PROC NEAR
- ;v1.2 Common routine to display error messages and terminate.
-
- push CS ;insure this is so
- pop DS
- ASSUME DS:MAIN
-
- push ax ;save ERRORLEVEL in AL
- mov bx,2 ;write to stderr
- mov ah,40h ;dos function number
- int 21h ;show error message
- pop ax ;restore ERRORLEVEL in AL
- mov ah,4CH ;terminate process
- int 21h
-
- Msg_Term ENDP
-
-
- CSEG ends
- end Begin ;start execution at Begin
-