Category : Pascal Source Code
Archive   : TSRSRC33.ZIP
Filename : MARK.ASM
; 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
;==============================================================================
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.3 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.3, 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
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/