home *** CD-ROM | disk | FTP | other *** search
- ;==========================================================================;
- ; Resident loader handler ;
- ; ;
- ; Copyright 1986, 1987, 1991 by H. Roy Engehausen. All rights reserved. ;
- ; This software may be freely distributed and used, but it may not ;
- ; under any circumstances be sold by anyone other than the author. ;
- ; It may be distributed by a commercial company as long as it is ;
- ; for no cost. ;
- ; ;
- ;==========================================================================;
-
- ;==========================================================================;
- ; Process the parameter list ;
- ;==========================================================================;
-
- MOV parm_flag,0 ; Start with zeros
-
- SUB BX,BX ; Start at front of parameter
-
- parm_loop: ; Do make things easier, we have
- ; DI with 1 higher than we really want
-
- CMP BL,psp_parm_len ; Are we done?
- JGE parm_end ; Yes...
-
- INC BX ;
-
- CMP psp_parm-1[BX],' ' ; Ignore blanks
- JE parm_loop ;
-
- CMP psp_parm-1[BX],'/' ; Ignore "/"
- JE parm_loop ;
-
- CMP psp_parm-1[BX],'f' ; Handle "f"
- JE parm_is_f ;
- CMP psp_parm-1[BX],'F' ; Handle "F"
- JNE parm_not_f ;
- parm_is_f:
- OR parm_flag,parm_flag_f ;
- JMP parm_loop ;
- parm_not_f:
-
- CMP psp_parm-1[BX],'r' ; Handle "r"
- JE parm_is_r ;
- CMP psp_parm-1[BX],'R' ; Handle "R"
- JNE parm_not_r ;
- parm_is_r:
- OR parm_flag,parm_flag_r ;
- JMP parm_loop ;
- parm_not_r:
-
- CMP psp_parm-1[BX],'u' ; Handle "u"
- JE parm_is_u ;
- CMP psp_parm-1[BX],'U' ; Handle "U"
- JNE parm_not_u ;
- parm_is_u:
- OR parm_flag,parm_flag_u ;
- JMP parm_loop ;
- parm_not_u:
-
- CMP psp_parm-1[BX],'d' ; Handle "d"
- JE parm_is_d ;
- CMP psp_parm-1[BX],'D' ; Handle "D"
- JNE parm_not_d ;
- parm_is_d:
- OR parm_flag,parm_flag_d ;
- JMP parm_loop ;
- parm_not_d:
-
- ; Invalid character if we get here
-
- MOV DX,OFFSET msgbad ; Message
- MOV AH,dos_write_line ; Send to output
- INT dos_vector_no ;
-
- INT dos_terminate_no ; Terminate!
-
- parm_end: ;
-
- ;==========================================================================;
- ; See if we already have a copy of this program resident ;
- ;==========================================================================;
-
- ;--------------------------------------------------------------------------;
- ; Using the parent PSP pointer, loop back until we find a block that ;
- ; points to itself. This belongs the the command executor (COMMAND.COM) ;
- ;--------------------------------------------------------------------------;
-
- ; CS assumed to point to current PSP
-
- MOV AX,CS ; Put current PSP pointer
- MOV ES,AX ; into ES
-
- psplp:
- MOV AX,WORD PTR ES:16H ; parent pointer
-
- MOV BX,ES ; Compare current PSP to parent PSP
- CMP AX,BX ;
- JZ pspfnd ; Both are the same, we have located
- MOV ES,AX ; COMMAND.COM
- JMP psplp ;
-
- pspfnd: ; here ES points to COMMAND.COM PSP
-
- ;--------------------------------------------------------------------------;
- ; The next step is to scan the memory block chain, looking to see if any ;
- ; of them belong to a resident copy of our program. ;
- ; ;
- ; The storage management routines in DOS build and maintain a set of ;
- ; contiguous memory blocks. Each block is prefixed by 16 bytes of control ;
- ; information. The block might contain a program (with a PSP at the ;
- ; front) or an Environment string (every program gets one of these when ;
- ; it's loaded to hold things like the full path name by which it was ;
- ; loaded) or some real data (since a program can request some storage from ;
- ; DOS and use it for any purpose it likes). The first 5 bytes of the ;
- ; control information contain: ;
- ; ;
- ; Offset Contents ; ;
- ; 0 flag byte (Z = last in chain, M = middle) ; ;
- ; 1 2 byte pointer to owning PSP (0 means ; ;
- ; this block is unallocated) ; ;
- ; 3 size of this block in paragraphs (size ; ;
- ; does not include the control information) ; ;
- ; ; ;
- ; Note that these fields are also UNDOCUMENTED. ; ;
- ; ; ;
- ; Since the memory blocks are contiguous, it's easy to use the size at ; ;
- ; offset 3 to step through the chain. ; ;
- ; ; ;
- ; We will only search blocks that are owned by COMMAND.COM's PSP. ; ;
- ; ; ;
- ;--------------------------------------------------------------------------;
-
- ; assumes es still points to COMMAND.COM's PSP
-
- MOV DX,-1 ; Indicate not found
- MOV BX,ES
- DEC BX ; Point to memory block
- MOV ES,BX
-
- memlp:
-
- ; Loop to here to check a memory block.
-
- CMP BYTE PTR ES:0,'Z' ; are we at the end?
- JZ memex ; Exit if yes
- MOV AX,WORD PTR es:1 ; PSP of owning prog
- DEC AX ; Memory block
- CMP AX,BX ; Does block contain a PSP owned by
- JNZ memnxt ; No... go to next one
- INC AX ; Yes, the back to psp
-
- ; here we have a PSP pointed to by AX
-
- MOV BX,CS ; Get my PSP address
- CMP AX,BX ; Is it me?
- JZ memex ; Yes... Exit!
-
- ; here we have a PSP pointed to by AX, so we test if it is
- ; a copy of us by comparing a string of characters in us
- ; with the same string in it. Once again we assume that
- ; assume that MARKER is a label at the start of the string
- ; and that MARKLEN is the length of the string.
-
- INC psp_count ; Bump the PSP counter
-
- PUSH ES ; Save current es
-
- MOV ES,AX ; We will compare the program pointed to
- ; by ES with ourselves pointed to by DS
-
- MOV SI,OFFSET marker ; Same offset for marker for both segments
- MOV DI,SI ;
-
- CLD ;
-
- MOV CX,marklen ; Length of fixed text
- REPE cmpsb ; Compare strings
- JNZ memnotus ; It is not us
-
- MOV psp_count,0 ; Clear the PSP counter
- MOV DX,ES ; And save pointer to resident copy
-
- memnotus:
-
- POP ES ; It's not so restore es
- ; And continue
-
- memnxt:
-
- MOV AX,ES:3 ; Size of this block
- MOV BX,ES ; Pointer to this block
- ADD BX,AX ;
- INC BX ; Add 1 for control info p'graph
- MOV ES,BX ; Point to next mem ctrl block
- jmp memlp ; And the loop back
-
- memyes:
- MOV DX,ES ; save pointer to resident copy
- POP ES ;
-
- memex: ;
-
- ; DX = -1 for resident copy not found
- ; DX = segment if we found the resident copy
- ; psp_count = Number of programs loaded after us
-
- ;==========================================================================;
- ; Check for duplicate load! Send error message and terminate as ;
- ; appropriate ;
- ;==========================================================================;
-
- CMP DX,-1 ; Not found?
- JE no_dupe_load ; That's right!
-
- TEST parm_flag,parm_flag_u ; Unload?
- JNZ no_dupe_load ; That's right!
- TEST parm_flag,parm_flag_f ; Duplicates allowed?
- JNZ no_dupe_load ; That's right!
-
- ; Error -- We found a copy but it wasn't permitted
-
- MOV DX,OFFSET msgdupe ; Message
- MOV AH,dos_write_line ; Send to output
- INT dos_vector_no ;
-
- INT dos_terminate_no ; Terminate!
-
- no_dupe_load:
-
- ;==========================================================================;
- ; Handle unload! ;
- ;==========================================================================;
-
- TEST parm_flag,parm_flag_u ; Unload?
- JNZ unload_to_do ;
- JMP no_unload ; Nope............
-
- unload_to_do:
-
- ;--------------------------------------------------------------------------;
- ; If we are not found then we can unload -- Give an error ;
- ;--------------------------------------------------------------------------;
-
- CMP DX,-1 ; Not found?
- JNE unload_found ; Nope............
-
- ; Error -- Unload but we can't find ourselves!
-
- MOV DX,OFFSET msgnodup ; Message
- MOV AH,dos_write_line ; Send to output
- INT dos_vector_no ;
-
- INT dos_terminate_no ; Terminate!
-
- unload_found:
-
- ;--------------------------------------------------------------------------;
- ; If we are not the last guy in the chain, give an error ;
- ;--------------------------------------------------------------------------;
-
- CMP psp_count,0 ; Any PSPs after us
- JE unload_last ; Nope............
-
- ; Error -- Unload but we are not last in chain
-
- MOV DX,OFFSET msgnotlast; Message
- MOV AH,dos_write_line ; Send to output
- INT dos_vector_no ;
-
- INT dos_terminate_no ; Terminate!
-
- unload_last:
-
- ;--------------------------------------------------------------------------;
- ; Unchain the interrupts that we have chained! ;
- ;--------------------------------------------------------------------------;
-
- MOV BX,DX ; BX = segment of copy we are unloading
- CLI ; No interrupts please
-
- ;--------------------------------------------------------------------------;
- ; Unchain the main interrupt ;
- ;--------------------------------------------------------------------------;
-
- MOV ES,BX ; Get segment to be unloaded
-
- PUSH DS ; Save DS
-
- MOV DX,ES:old_bios_vector ; Get old vector
- MOV DS,ES:old_bios_vector+2 ;
-
- MOV AL,rs232_vector_no ; vector #
-
- MOV AH,dos_set_vector ; DOS call #25H -- Set vector
- INT dos_vector_no ; Do it
-
- POP DS ; Restore DS
-
- ;--------------------------------------------------------------------------;
- ; Loop thru all the com blocks ;
- ;--------------------------------------------------------------------------;
-
- MOV SI,OFFSET com_start ; Place to start the comm loop
-
- unload_loop:
-
- MOV DI,com_init_count ; Get number of ports left to do
-
- ;--------------------------------------------------------------------------;
- ; Unchain the vector ;
- ;--------------------------------------------------------------------------;
-
- MOV ES,BX ; Get segment to be unloaded
-
- MOV DX,ES:old_interrupt_vec_off[DI] ; Get previous offset
- MOV AX,ES:old_interrupt_vec_seg[DI] ; Get previous segment
-
- OR AX,AX ; Test to see if used
- JZ unload_no_int ; No interrupt here
-
- PUSH DS ; Save DS
- MOV DS,AX ; Set DS to segement of interrupt guy
-
- MOV AL,ES:hiv[SI] ; Get the hardware interrupt vector address
-
- MOV AH,dos_set_vector ; DOS call #25H -- Set vector
- INT dos_vector_no ; Do it
-
- POP DS ; Restore DS
-
- unload_no_int:
-
- INC DI ; Bump counter
- INC DI ; Twice for words
- MOV com_init_count,DI ; and then save it
-
- ;--------------------------------------------------------------------------;
- ; Loop thru the next comm port ;
- ;--------------------------------------------------------------------------;
-
- MOV SI,com_next[SI] ; Pointer to next com port block
-
- CMP SI,0 ; Anything left to be done?
- JE unload_intr_done ; Nope...
- JMP unload_loop ; Yep.. Loop back
-
- unload_intr_done:
-
- ;--------------------------------------------------------------------------;
- ; Unchain the timer interrupt ;
- ;--------------------------------------------------------------------------;
-
-
- MOV DX,ES:timer_old ; Get previous offset
- MOV AX,ES:timer_old+2 ; Get previous segment
-
- OR AX,AX ; Was it snatched?
- JZ unload_no_timer ; Nope
-
- PUSH DS ; Save DS
- MOV DS,AX ; Set DS to segement of interrupt guy
-
- MOV AH,dos_set_vector ; DOS call #25H -- Set vector
- MOV AL,timer_vector_no ; Timer vector #
- INT dos_vector_no ; Do it
-
- POP DS ; Restore DS
-
- unload_no_timer: ;
-
- ;--------------------------------------------------------------------------;
- ; Enable interrupts ;
- ;--------------------------------------------------------------------------;
-
- STI ; Enable CPU to receive interupts
-
- ;--------------------------------------------------------------------------;
- ; Successful unload message here ;
- ;--------------------------------------------------------------------------;
-
- MOV DX,OFFSET msgunload ; Message
- MOV AH,dos_write_line ; Send to output
- INT dos_vector_no ;
-
- ;--------------------------------------------------------------------------;
- ; Now free the program whose PSP is pointed to by DX ;
- ;--------------------------------------------------------------------------;
-
- MOV ES,BX ; Point to PSP to be dropped
- MOV AH,dos_free_mem ;
- INT dos_vector_no ; Free it
-
- MOV ES,ES:psp_environ_ptr ; Segment address of environment
- MOV AH,dos_free_mem ;
- INT dos_vector_no ; Free it
-
- ;--------------------------------------------------------------------------;
- ; Unload complete ;
- ;--------------------------------------------------------------------------;
-
- INT dos_terminate_no ; Terminate!
-
- ;==========================================================================;
- ; Handle reset ;
- ;==========================================================================;
-
- no_unload:
-