home *** CD-ROM | disk | FTP | other *** search
- ;****************************************************************************
- ; REMOVE removes a bookmark placed in memory by INSTALL. Its syntax is:
- ;
- ; REMOVE [bookmark] [/L]
- ;
- ; where "bookmark" is the name of the bookmark to be removed from memory,
- ; and /L lists the bookmarks that are currently resident in memory. When
- ; a bookmark is removed, all the TSRs installed above it are removed also.
- ; Run with no command line parameters, REMOVE removes the highest bookmark
- ; in memory.
- ;****************************************************************************
-
- nextblock equ 0103h ;Offset of NEXTBLOCK field
- bm_addr equ 0105h ;Offset of bookmark field
- vectors equ 0133h ;Offset of vector field
-
- code segment
- assume cs:code,ds:code
- org 100h
- begin: jmp main
-
- helpmsg db "Removes a bookmark created with INSTALL."
- db 13,10,13,10
- db "REMOVE [bookmark] [/L]",13,10,13,10
- db " bookmark Name of the bookmark to remove.",13,10
- db " /L List the bookmarks currently "
- db "installed.",13,10,13,10
- db "Run with no parameters, REMOVE removes the most "
- db "recently installed bookmark.",13,10
- db "When a bookmark is removed, all the TSRs installed "
- db "after it are removed, too.",13,10,"$"
-
- errmsg1 db "Syntax: REMOVE [bookmark] [/L]",13,10,"$"
- errmsg2 db "Requires DOS 3.0 or higher",13,10,"$"
- errmsg3 db "There are no bookmarks installed",13,10,"$"
- errmsg4 db "There is no bookmark by that name",13,10,"$"
- errmsg5 db "Memory deallocation failed",13,10,"$"
-
- msg1 db "REMOVE 1.3 Copyright (c) 1993 Jeff Prosise",13,10
- db "From: PC Magazine DOS 6 Memory Management "
- db "with Utilities",13,10,13,10
- db "Bookmark $"
- msg2 db " removed"
- crlf db 13,10,"$"
-
- lastblock dw ? ;Segment of last block
- bookmark db 33 dup (0Dh) ;Bookmark name
- signature db 0,1,2,"INSTALL",2,1,0 ;INSTALL signature
-
- ;****************************************************************************
- ; Procedure MAIN
- ;****************************************************************************
-
- main proc near
- cld ;Clear direction flag
- mov si,81h ;Point SI to command line
- call scanhelp ;Scan for "/?" switch
- jnc checkver ;Branch if not found
- mov ah,09h ;Display help text and exit
- mov dx,offset helpmsg ;with ERRORLEVEL=0
- int 21h
- mov ax,4C00h
- int 21h
- ;
- ; Check the DOS version.
- ;
- checkver: mov dx,offset errmsg2 ;Exit if DOS version
- mov ah,30h ;is less than 3.0
- int 21h
- cmp al,3
- jae checkins
-
- error: mov ah,09h ;Display error message and
- int 21h ;exit with ERRORLEVEL=1
- mov ax,4C01h
- int 21h
-
- checkins: call check_install ;See if INSTALL is installed
- mov dx,offset errmsg3
- jnc error ;Exit if it's not
- ;
- ; Parse the command line.
- ;
- mov lastblock,cs ;Initialize LASTBLOCK
- mov si,81h ;Reset SI
- call findchar ;Find the first parameter
- jc search1 ;Branch if there are none
- cmp byte ptr [si],"/" ;Branch if the character
- jne parse ;is not a "/"
- ;
- ; Process a /L switch.
- ;
- list: inc si ;Skip the "/" character
- lodsb ;Get the next character
- and al,0DFh ;Capitalize it
- mov dx,offset errmsg1 ;Initialize error pointer
- cmp al,"L" ;Error if the character is
- jne error ;not an "L"
-
- nextname: mov di,bm_addr ;Point DI to bookmark name
- call dos_out ;Display bookmark name
- mov ah,09h ;Move the cursor to the
- mov dx,offset crlf ;next line
- int 21h
- cmp word ptr es:[nextblock],0FFFFh ;Exit if this is the
- je list_exit ;last block
- mov es,es:[nextblock] ;Get segment of next block
- jmp nextname ;Go back and output its name
-
- list_exit: mov ax,4C00h ;Exit with ERRORLEVEL=0
- int 21h
- ;
- ; Read the bookmark name from the command line.
- ;
- parse: mov di,offset bookmark ;Point DI to buffer
- mov cx,32 ;Initialize counter
- parse1: lodsb ;Get a character
- cmp al,"a" ;Capitalize it if it's
- jb parse2 ;between "a" and "z"
- cmp al,"z"
- ja parse2
- and al,0DFh
- parse2: mov [di],al ;Store it
- inc di ;Increment DI
- cmp al,0Dh ;Branch if it was a carriage
- je search ;return
- loop parse1 ;Loop back for more
- ;
- ; Search out a bookmark.
- ;
- search: mov si,offset bookmark ;Point SI to local name
- mov di,bm_addr ;Point DI to remote name
- call compare_names ;Compare the two
- je endchain ;Branch if they're equal
- mov dx,offset errmsg4
- cmp word ptr es:[nextblock],0FFFFh
- je error ;Error if last block
- mov lastblock,es ;Save last block address
- mov es,es:[nextblock] ;Get address of next block
- jmp search ;Return to search loop
-
- search1: cmp word ptr es:[nextblock],0FFFFh
- je endchain ;Branch if last block
- mov lastblock,es ;Save last block address
- mov es,es:[nextblock] ;Get address of next block
- jmp search1 ;Continue the search
- ;
- ; Terminate the chain of INSTALLed blocks and restore interrupt vectors.
- ;
- endchain: push es ;Save ES
- mov es,lastblock ;Retrieve last block address
- mov word ptr es:[nextblock],0FFFFh ;Terminate the chain
- pop es ;Restore ES
- mov lastblock,es ;Save ES in LASTBLOCK
-
- push ds ;Save DS and ES
- push es
- mov ax,es ;Point DS:SI to copy of
- mov ds,ax ;interrupt vectors in
- assume ds:nothing ;INSTALLed block
- mov si,vectors
- sub di,di ;Point ES:DI to 0000:0000
- mov es,di
- mov cx,512 ;Initialize counter
- cli ;Disable interrupts
- rep movsw ;Restore interrupt vectors
- sti ;Enable interrupts
- pop es ;Restore DS and ES
- pop ds
- assume ds:code
- ;
- ; Search out every PSP block above INSTALL and deallocate the memory that
- ; belongs to it.
- ;
- mov bx,es ;Transfer ES to BX
- mov ah,49h ;Deallocate the memory used
- int 21h ;by INSTALL
- mov dx,offset errmsg5 ;Initialize error pointer
- jc error1 ;Error if call failed
-
- remove: dec bx ;Point BX to MCB
- mov es,bx ;Transfer BX to ES
- add bx,es:[03h] ;Compute next MCB address
- inc bx
- mov es,bx ;Transfer segment to ES
- inc bx ;Point BX to segment beyond
- cmp bx,es:[01h] ;Does the segment own itself?
- jne remove ;No, then continue searching
- mov ax,cs ;Record current segment in AX
- cmp bx,ax ;Have we reached our own PSP?
- je done ;Yes, then we're done
-
- push bx ;Save PSP segment address
- call freemem ;Free all memory it owns
- pop bx ;Retrieve the address
- mov dx,offset errmsg5 ;Loop back if no error
- jnc remove ;occurred
-
- error1: jmp error ;Exit on error
- ;
- ; Announce that REMOVE succeeded and terminate.
- ;
- done: mov ah,09h ;Display message verifying
- mov dx,offset msg1 ;that the book mark was
- int 21h ;removed
- mov es,lastblock
- mov di,bm_addr
- call dos_out
- mov ah,09h
- mov dx,offset msg2
- int 21h
-
- mov ax,4C00h ;Exit with ERRORLEVEL=0
- int 21h
- main endp
-
- ;****************************************************************************
- ; FINDCHAR advances SI to the next non-white-space character. On return,
- ; carry set indicates EOL was encountered.
- ;****************************************************************************
-
- findchar proc near
- lodsb ;Get the next character
- cmp al,09h ;Loop if tab
- je findchar
- cmp al,20h ;Loop if space
- je findchar
- cmp al,2Ch ;Loop if comma
- je findchar
- dec si ;Point SI to the character
- cmp al,0Dh ;Exit with carry set if end
- je eol ;of line is reached
-
- clc ;Clear carry and exit
- ret
-
- eol: stc ;Set carry and exit
- ret
- findchar endp
-
- ;****************************************************************************
- ; SCANHELP scans the command line for a /? switch. If found, carry returns
- ; set and SI contains its offset. If not found, carry returns clear.
- ;****************************************************************************
-
- scanhelp proc near
- push si ;Save SI
- scanloop: lodsb ;Get a character
- cmp al,0Dh ;Exit if end of line
- je scan_exit
- cmp al,"?" ;Loop if not "?"
- jne scanloop
- cmp byte ptr [si-2],"/" ;Loop if not "/"
- jne scanloop
-
- add sp,2 ;Clear the stack
- sub si,2 ;Adjust SI
- stc ;Set carry and exit
- ret
-
- scan_exit: pop si ;Restore SI
- clc ;Clear carry and exit
- ret
- scanhelp endp
-
- ;****************************************************************************
- ; CHECK_INSTALL returns carry set if a copy of INSTALL is installed,
- ; carry clear if it's not. If carry returns set, AH holds INSTALL's
- ; multiplex ID number and ES holds its segment address.
- ;****************************************************************************
-
- check_install proc near
- mov ax,0C000h ;Initialize AH and AL
- mov cx,40h ;Initialize count
-
- chinst1: push ax ;Save AX and CX
- push cx
- sub di,di ;Set ES and DI to 0
- mov es,di
- int 2Fh ;Interrupt 2Fh
- cmp al,0FFh ;Nothing here if AL isn't
- jne chinst2 ;equal to FFH
-
- mov si,offset signature ;See if program signature
- mov cx,13 ;appears at the address
- repe cmpsb ;returned in ES:DI
- jne chinst2 ;Branch if it does not
-
- pop cx ;Clear the stack and exit
- pop ax ;with carry set
- stc
- ret
-
- chinst2: pop cx ;Retrieve AX and CX
- pop ax
- inc ah ;Next multiplex ID
- loop chinst1 ;Loop until done
-
- clc ;Exit with carry clear
- ret
- check_install endp
-
- ;****************************************************************************
- ; FREEMEM frees all the memory blocks owned by the process whose PSP
- ; address is passed in BX. Carry is set on return if a call to release
- ; a block of memory failed.
- ;****************************************************************************
-
- freemem proc near
- push bx ;Save BX
- mov ah,52h ;Get address of the first
- int 21h ;MCB with DOS function 52H
- mov dx,es:[bx-2] ;Copy the address to DX
- mov es,dx ;Also copy it to ES
- pop bx ;Restore BX
-
- free1: cmp bx,es:[01h] ;Branch if the ownership
- jne free2 ;word does not match
-
- inc dx ;Increment DX
- mov es,dx ;Point ES to segment
- mov ah,49h ;Deallocate the segment
- int 21h
- jc free_exit ;Exit if called failed
- dec dx ;Decrement DX
- mov es,dx ;Point ES back to the MCB
-
- free2: add dx,es:[03h] ;Compute the address of the
- inc dx ;next MCB
- mov es,dx ;Transfer address to ES
- cmp byte ptr es:[00h],"Z" ;End of the MCB chain?
- jne free1 ;No, then continue the search
- clc ;Clear carry and exit
- free_exit: ret
- freemem endp
-
- ;****************************************************************************
- ; COMPARE_NAMES compares the two ASCII strings addressed by DS:SI and ES:DI.
- ; On return, the Z flag indicates whether or not the two are equal.
- ;****************************************************************************
-
- compare_names proc near
- lodsb ;Get a character
- cmp al,0Dh ;Exit if it's a carriage
- je compare_exit ;return
- scasb ;Compare it ES:[DI]
- je compare_names ;Loop back if they're euqal
- compare_exit: ret ;Return to caller
- compare_names endp
-
- ;****************************************************************************
- ; DOS_OUT displays the ASCII string pointed to by ES:DI.
- ;****************************************************************************
-
- dos_out proc near
- mov dl,es:[di] ;Get a character
- cmp dl,0Dh ;Exit if it's a carriage
- je dos_exit ;return
- mov ah,02h ;Output it using DOS
- int 21h ;function 02H
- inc di ;Advance DI to next one
- jmp dos_out ;Loop until done
- dos_exit: ret
- dos_out endp
-
- code ends
- end begin
-