;**********************************************************;
;* Self High-Loading TSR Program -- 32 bytes resident!! *;
;* By Tenie Remmel *;
;**********************************************************;
Ideal
Model Tiny
P186
Codeseg
Org 100h
Proc Prog
mov dx,offset RName ;Only leaves 32 bytes!
mov si,offset RName ;also name offset
mov cx,0 ;No int. vectors
jmp TSRHi ;TSR procedure
RName db 'Test',0 ;This is the resident name
EndP Prog
Proc TSRHi ;Registers on entry:
;
; DX = last byte of program
; CS = segment of program
; CS:SI = resident name (8 bytes)
; CX = Number of vectors to set
; CS:BX = Vector list
;
; Vector list format: <offset> <number> ...
; -word- -byte-
pusha ;Save all registers
push cs ;DS = CS
pop ds
mov ah,4Ah ;Reallocate Memory
mov bx,1000h ;BX = 64K
push cs ;ES = code segment
pop es
int 21h ;DOS services
mov ah,49h ;Free memory
mov es,[2Ch] ;Environment block
int 21h ;DOS services
mov ax,5800h ;Get Alloc. Strategy
int 21h ;DOS services
push ax ;Save value
mov ax,5802h ;Get UMB Link
int 21h ;DOS services
push ax ;Save value
mov ax,5803h ;Set UMB Link
mov bx,1 ;1 = Link ON
int 21h ;DOS services
mov ax,5801h ;Set Alloc. Strategy
mov bx,82h ;Last Fit, UMBs First
int 21h ;DOS services
mov ah,48h ;Allocate Memory
mov bx,dx ;BX = last byte
sub bx,0F1h ;BX - 100h + 0Fh
shr bx,4 ;BX = size in paras
int 21h ;DOS services
jc _NoMem ;Jump if error
dec ax ;AX = MCB seg.
mov es,ax ;ES = AX
inc ax ;AX = memory block
mov [es:1],ax ;Set owner to itself
mov di,8 ;Move name to MCB:8
mov cx,4 ;8 bytes = 4 words
rep movsw ;Move by words
mov ax,5803h ;Set UMB Link
pop bx ;to old value
int 21h ;DOS services
mov ax,5801h ;Set Alloc. Strategy
pop bx ;to old value
xor bh,bh
int 21h ;DOS services
mov ax,es ;AX = new CS segment
sub ax,0Fh
mov es,ax ;ES = AX
popa ;Restore original regs
mov si,100h ;SI = 100h
mov di,si ;DI = 100h
push cx ;Save CX
mov cx,dx ;CX = last byte
sub cx,100h ;CX = length
rep movsb ;Move data
pop cx ;Restore CX
jcxz _NoVects ;No vectors to set?
mov ah,25h ;Set Interrupt Vector
push es ;DS = ES
pop ds
_SetIVect: lodsw ;Load offset
mov dx,ax ;into DX
lodsb ;Load int. number
int 21h ;Set vector
loop _SetIVect ;Loop back
_NoVects: mov ax,4C00h ;Return with code 0
int 21h ;DOS services
_NoMem: mov ax,5803h ;Set UMB Link
pop bx ;to old value
int 21h ;DOS services
mov ax,5801h ;Set Alloc. Strategy
pop bx ;to old value
xor bh,bh
int 21h ;DOS services
mov ax,cs ;ES = MCB segment
dec ax
mov es,ax
mov di,8 ;Move name to MCB:8
mov cx,4 ;8 bytes = 4 words
rep movsw ;Move by words
popa ;Restore original regs
push dx ;Save DX
jcxz _NoVects1 ;No vectors to set?
mov ah,25h ;Set Interrupt Vector
_SetIVect1: lodsw ;Load offset
mov dx,ax ;into DX
lodsb ;Load int. number
int 21h ;Set vector
loop _SetIVect1 ;Loop back
_NoVects1: mov ax,3100h ;TSR service, code 0
pop dx ;Restore DX
add dx,0Fh ;DX = size in paras,
shr dx,4 ;rounded up
int 21h ;DOS services
EndP TSRHi
End Prog