home *** CD-ROM | disk | FTP | other *** search
- ;==============================================================================
- ; MARK.ASM - mark a position in memory,
- ; above which TSRs will later be cleared by RELEASE
- ; MARK can be called multiple times, each RELEASE will clear
- ; above the last MARK called.
- ; If MARK is called with something on the command line, that text will
- ; be stored in the program segment prefix at offset 80H, where it is
- ; later accessible to RELEASE for a "named" release.
- ;
- ; Syntax: MARK [/Q] [!][MarkName]
- ;==============================================================================
- ; written for TASM
- ; Copyright (c) 1986,1991 Kim Kokkonen, TurboPower Software.
- ; May be freely distributed but not sold except by permission.
- ; telephone: 719-260-6641, Compuserve 76004,2611
- ;==============================================================================
- ; version 1.0 2/8/86
- ; original public release
- ; (thanks to Neil Rubenking for an outline of the method used)
- ; :
- ; long intervening history
- ; :
- ; version 3.0 9/24/91
- ; add Quiet option
- ; add code for tracking high memory
- ; version 3.1 11/4/91
- ; no change
- ; version 3.2 11/22/91
- ; change method of accessing high memory
- ; store parent len as well as parent segment
- ; version 3.3 1/8/92
- ; no change
- ; version 3.4 2/14/92
- ; no change
- ;==============================================================================
-
- Cseg segment public para
- assume cs:Cseg, ds:Cseg, es:nothing
- locals @@
-
- org 81H
- cmdlin label byte ;first character of command line
-
- org 100H
- comentry: jmp doit
-
- ;put the following in the MAP file
- public idstr,vector,egasav,intcom,emscnt,emsmap
-
- idstr db 'MM3.4 TSR' ;used to find this TSR
- firsthimcb dw 0 ;segment of first mcb in high mem
-
- ;**** the following will be overwritten by the vector table image *************
- ;success message and version number
- didit db 'MARK 3.4, Copyright 1991 TurboPower Software',13,10
- didit2 db 'Marked current memory position',13,10,36
- errst db 'Invalid command line',13,10,36
- ;file name for testing EMS presence
- emsnm db 'EMMXXXX0',0
- quiet db 0
- xmsadr label dword ;XMS control address
- xmsxxx dw 2 dup (0)
- ;******************************************************************************
-
- vector equ 0120H ;offset in code seg where vector table is copied
- veclen equ 0400H ;1024 bytes for vectors
- egasav equ vector+veclen
- egalen equ 8 ;8 bytes for EGA save area
- intcom equ egasav+egalen
- intlen equ 10H ;16 bytes for interapps communication area
- parent equ intcom+intlen
- parlen equ parent+2 ;parent's PSP length
- emscnt equ parlen+2
- emsmap equ emscnt+2
- ;mcbcnt and mcbmap actually follow after used portion of emsmap
- mcbcnt equ emsmap+400H ;count of allocated mcbs
- mcbmap equ mcbcnt+2 ;array of mcb segments
- ;newloc follows after the longest possible emsmap and mcbmap
- newloc equ mcbmap+400H ;location of relocated code
-
- ;*****************************************************************************
-
- doit proc near
-
- ;find first mcb in high memory, if any
- mov ax,3000h ;get DOS version
- int 21H
- cmp al,3
- jb @@7 ;no XMS driver possible
- mov ax,4300h
- int 2Fh ;multiplex call for XMS
- cmp al,80h ;proper signature?
- jne @@7 ;no XMS driver
- mov ax,4310h ;get XMS control address
- int 2Fh
- mov xmsxxx,bx ;save it
- mov xmsxxx[2],es
- mov ah,10h
- mov dx,0FFFFh
- call xmsadr ;ask to allocate FFFF paras of UMB
- cmp bl,0B0h ;will fail with B0 if UMBs avail
- je @@0
- cmp bl,0B1h ;will fail with B1 if UMBs all allocated
- jne @@7 ;no UMBs exist
- @@0: int 12H
- mov cl,6
- shl ax,cl ;get segment of top of memory
-
- @@1: mov es,ax
- cmp byte ptr es:[0000h],'M' ;potential mcb?
- jnz @@6 ;not an mcb, try next segment
- @@2: mov cx,ax ;save potential start mcb in cx
- @@3: inc ax
- add ax,es:[0003h] ;ax = start of next mcb
- jc @@5 ;can't be an mcb if we wrapped
- mov es,ax ;address of next mcb
- mov dl,es:[0000h]
- cmp dl,'M'
- jz @@3 ;good start mcb
- cmp dl,'Z'
- jz @@9 ;good end mcb
- @@5: mov ax,cx ;restore last start segment
- @@6: cmp ax,0FFFFh ;top of memory?
- je @@7
- inc ax ;try next segment
- jmp @@1
-
- @@7: xor cx,cx ;no matching UMB
- @@9: mov firsthimcb,cx ;store first high mcb
-
- ;relocate ourselves out of the way
- push cs
- pop es
- mov di,newloc
- push di ;will act as a return address
- mov si,offset parse
- mov cx,lastcode-parse
- cld
- rep movsb
- ret ;"return" to the relocated code
-
- ;scan command line for /Q option
- parse: mov si,offset cmdlin
- cld
- get1: lodsb
- cmp al,13 ;end of command line?
- je pmess
- cmp al,'/' ;option switch?
- je getop
- cmp al,'-'
- jne get1 ;loop around
- getop: mov di,si ;save option position
- lodsb
- cmp al,'a'
- jb noup
- cmp al,'z'
- ja noup
- and al,0DFH ;uppercase
- noup: cmp al,'Q'
- jne error
- mov quiet,1 ;set quiet flag
- dec di
- mov al,' '
- stosb ;clear option
- stosb
- jmp get1 ;loop around
-
- error: mov dx,offset errst
- mov ah,9
- int 21H
- mov ax,4C01H
- int 21H
-
- ;print message if not quiet
- pmess: cmp quiet,0
- jnz chkems
- mov dx,offset didit
- mov ah,9
- int 21H ;write success message
-
- ;determine whether EMS is present
- chkems: mov dx,offset emsnm
- mov ax,3D00H
- int 21H
- jnc emspres ;EMS driver installed
- xor bx,bx
- jmp short stocnt
-
- ;EMS present, close the open handle first
- emspres:
- mov bx,ax
- mov ah,3EH
- int 21H
-
- ;store the EMS page map
- mov ah,4DH
- mov di,emsmap
- xor bx,bx ;required by some versions of EMM
- cld ;required by some versions of EMM
- int 67H
-
- ;store the number of active EMS handles
- stocnt:
- mov ds:[emscnt],bx ;count of active handles
-
- ;store the interrupt vector table (overwrites initial messages)
- xor ax,ax
- mov ds,ax ;source address segment 0
- assume ds:nothing
- xor si,si ;offset 0
- mov di,vector ;destination offset, es=cs already
- mov cx,veclen shr 1 ;count of words to store
- rep movsw ;copy vectors to our table
-
- ;store the EGA save area
- mov ax,40H
- mov ds,ax ;point to BIOS data area
- mov si,00A8H ;EGA save area pointer
- mov di,egasav
- mov cx,egalen shr 1
- rep movsw ;copy information to our save area
-
- ;store the interapplications communication area
- mov si,00F0H ;interapps communication area address
- mov di,intcom
- mov cx,intlen shr 1
- rep movsw ;copy information to our save area
-
- ;store the parent's PSP segment
- push cs
- pop ds ;ds = cs
- assume ds:cseg
- mov ax,ds:[16h] ;get parent's PSP from our PSP
- mov ds:[parent],ax ;store in data save area
- dec ax
- mov es,ax
- mov ax,es:[0003h] ;get length of parent's psp
- mov ds:[parlen],ax ;store in data save area
-
- ;store the mcb chain
- mov ah,52H ;get first mcb segment
- int 21H
- mov ax,es:[bx-2] ;ax=first mcb
- push cs
- pop es ;es=cs
-
- mov di,cs:[emscnt] ;get starting address of mcbmap
- shl di,1
- shl di,1
- add di,emsmap
- mov si,di ;cs:[si] -> mcbcnt
- add di,2 ;cs:[di] -> mcbmap
- xor cx,cx ;cx will count mcbs
- cld
- push ds
- assume ds:nothing
-
- mcbnext:
- stosw ;store mcb segment held by ax
- mov ds,ax ;ds:[0] points to mcb
- mov ax,ds:[1] ;get mcb owner
- stosw ;store it
- inc cx ;increment count
- cmp byte ptr ds:[0],'Z' ;end of mcb chain?
- je mcbdone
- mov ax,ds ;restore ax to mcb segment
- inc ax ;skip over mcb itself
- add ax,ds:[3] ;add length of memory block
- jmp mcbnext
-
- mcbdone:mov ax,firsthimcb ;check for high memory
- or ax,ax
- jz mcbend
- mov firsthimcb,0 ;only do it once
- jmp mcbnext
-
- mcbend: pop ds
- assume ds:cseg
-
- ;terminate and stay resident
- gores: mov [si],cx ;store mcbcnt
- mov dx,di ;dx = past last used mcb segment
- add dx,000FH ;add paragraph roundup
- mov cl,4
- shr dx,cl ;convert to paragraphs
- mov ax,3100H
- int 21H ;terminate but stay resident
-
- lastcode:
- doit endp
-
- Cseg ends
- end ComEntry