Search code examples
assemblydostsr

How to remove TSR(Terminate-Stay-Resident) program from memory


I have a very basic TSR code. What it does is, when I type "D" key, it will print "E" on the screen, nothing else.
What I want to do is: when i press "ESC" button I want to remove my TSR and return to original BIOS routine.

org 100h

equ 060h            

EOI            equ 020h         
Master_8259    equ 020h

main:
    call _inst_09

_inst_09:
    cli
    xor     ax, ax
    mov     es, ax
    mov     bx, [es:09h*4]
    mov     [stari_int09_off], bx 
    mov     bx, [es:09h*4+2]
    mov     [stari_int09_seg], bx

    mov     dx, tastatura
    mov     [es:09h*4], dx
    mov     ax, cs
    mov     [es:09h*4+2], ax
    sti

    mov ax,3100h
    mov dx,500
    int 21h
    ret

tastatura:  
    push    ax
    in      al, KBD             ; Ucitati scan_code iz I/O registra tastature  
    mov    [kbdata], al
    cmp byte[kbdata],20h
    je .lup
    mov     al, EOI             ; Kod za End Of Interrupt (EOI)
    out     Master_8259, al     ; Poslati EOI na Master PIC (dozvola novih prekida)
    pop     ax
    iret
.lup:
    mov al,45h
    mov ah,0eh
    int 10h
    mov     al, EOI             
    out     Master_8259, al     
    pop     ax
    iret

stari_int09_seg: dw 0
stari_int09_off: dw 0

kbdata:     db 0                                   

%include "ekran.asm"

I know that i need to uninstall my modified interupt but my program became iresponsive after i did so.
This would be the unnistaling procedure

_uninst_09:
cli
xor     ax, ax
mov     es, ax
mov     ax, [stari_int09_seg]
mov     [es:09h*4+2], ax
mov     dx, [stari_int09_off]
mov     [es:09h*4], dx
sti
ret

The trick is I don't know where to put it. I tried checking if ESC is pressed and then jump to this procedure but it seems it is not working.


Solution

  • Restore all hooked interrupt vectors to their original values, close all files (if any), free all dynamic memory allocated from DOS (if any), then free the program area itself. Depending on whether the TSR is a COM file or an EXE file, its starting address would be different. For COM files, the program memory starts at the file beginning; for EXE files, it's slightly more tricky. Then return from the interrupt handler as usual, it won't be invoked ever again.

    To free DOS memory, use interrupt 21h, function 49h.

    EDIT: your problem is with your interrupt handler. It doesn't process the keyboard input right, thus breaking the keyboard for the foreground process.

    In the handler, call the original one first thing (with respect to the fact that it's an interrupt handler):

    tastatura:  
        push es
        push ax
        mov ax, [stari_int09_seg]
        mov es, ax
        mov ax, [stari_int09_off]
        pushf
        call es:ax
    

    Then use int 16 to read the keyboard input.