1642 .MODEL TINY .386 .CODE ORG 100h start: jmp main ;**************************** Resident data org_int9 dd ? refresh_toggle db 0 ;**************************** NewInt9 -- New INT9 (key-press) proc. newint9 PROC sti push ax in al,60h ; Get scancode from keyboard processor cmp al, 27h ; Check if hotkey (Alt-™) jnz no_hotkey push es ; look into BIOS data area sub ax, ax ; (segment 0) to check shift state mov es, ax mov ax, es:[417h] ; Get SHIFT-key flags test ax, 0000000000001000b ; Check if Alt-key pressed pop es jz no_hotkey cli ; Disable interrupts while resetting in al, 61h ; Get current port 61h state or al, 10000000b ; Turn on bit 7 to signal clear keybrd out 61h, al ; Send to port and al, 01111111b ; Turn off bit 7 to signal break out 61h, al ; Send to port push bx mov ah, 12h ;Disable/enable screen refresh xor cs:refresh_toggle,1 mov al,cs:refresh_toggle mov bl,36h int 10h pop bx mov al, 20h ; Reset interrupt controller out 20h, al sti ; Reenable interrupts pop ax iret no_hotkey: pop ax ; Recover AX and fall through cli ; Interrupts cleared for service jmp cs:org_int9 ; jump to old Int 09 routine newint9 ENDP ;/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ Transient Section ;**************************** Transient data header db 'Screen Saver installed. Press Alt-™ to activate/deactivate.',13,10,'$' uninstalled db 'Un' installed db 'Installed Successfully',13,10,'$' syntax db 'Syntax: SCRSAV [/U]',13,10,'$' nomemory db 'Out of memory',13,10,'$' alreadyin db 'Already installed',13,10,'$' notfound db 'Resident copy not found',13,10,'$' cantunload db 'Can''t uninstall',13,10,'$' resname db 'ScrSav ' resseg dw 0 ;**************************** Main -- Main procedure main PROC mov ah,9 ;Print install message mov dx, offset header int 21h call findres ;Find resident copy mov al,'/' ;Search for slash xor cx, cx ;in command line mov cl, byte ptr cs:[80h] mov di, 81h repne scasb jne nounload ;No slash, don't unload mov dx, offset syntax ;DX = 'Syntax:' string cmp byte ptr[di], 'U' ;/U or /u, unload je unload cmp byte ptr[di], 'u' je unload cmp byte ptr[di], '?' ;/?, print syntax je error nounload: mov dx, offset alreadyin ;Point DX to error string cmp resseg, 0 ;Already installed? jne error cld ;Clear direction flag mov ax, offset lastbyte ;AX = last byte + 256 inc ah cmp ax, sp ;Check for too little memory jbe memOK mov dx, offset nomemory ;Print 'Out of memory' string error: mov ah, 9 int 21h mov ax, 4C01h ;Exit with error int 21h memOK: mov sp, ax ;Shrink stack jmp load ;Jump to Load procedure main ENDP ;**************************** Load -- TSR loader procedure load PROC mov ah,49h ;Free environment segment mov es, cs:[2Ch] int 21h mov ax, 3509h ;Get and store old INT9 address int 21h mov word ptr[org_int9], bx mov word ptr[org_int9+2], es mov ax, 2509h ;Set new INT16 handler mov dx, offset newint9 int 21h mov ax, cs ;ES = MCB segment (CS - 1) dec ax mov es, ax mov si, offset resname ;Change resident name mov di, 8 mov cx, di rep movsb mov ah, 9 ;Print 'Installed' string mov dx, offset installed int 21h mov dx, offset header-1 ;Last byte of program lastbyte: int 27h ;DOS TSR service load ENDP ;**************************** Unload -- Uninstall procedure unload PROC mov cx, resseg ;CX = resident segment mov dx, offset notfound ;Point DX to error string test cx, cx ;Make sure it's in memory je error mov dx, offset cantunload ;Point DX to error string mov ax, 3509h ;Check to make sure that the int 21h ;interrupts still point to cmp bx, offset newint9 ;the resident copy... jne error mov es, resseg ;ES = resident segment mov ax, 2509h ;Reset INT9 vector mov dx, word ptr es:[org_int9] mov ds, word ptr es:[org_int9+2] int 21h mov ah, 49h ;Release memory segment int 21h push cs ;DS = CS pop ds mov byte ptr[installed], 'i';Fix 'Uninstalled' string mov ah,9 ;Print 'Uninstalled' string mov dx, offset uninstalled int 21h mov ax, 4C00h ;Quit program int 21h unload ENDP ;**************************** FindRes -- Find resident copy findres PROC pusha ;Save registers push es mov ax,5802h ;Save UMB link status int 21h push ax mov ax, 5803h ;Link UMBs mov bx, 1 int 21h mov ah, 52h ;Get Internal Config Table int 21h sub bx, 2 ;BX = first MCB mov bx, es:[bx] fr_lp: mov es, bx ;ES = MCB segment cmp word ptr es:[9], 7263h ;Check for signature je fr_found add bx, es:[3] ;Step to next one inc bx cmp byte ptr es:[0],'Z' ;Last one in chain? jne fr_lp ;Loop back mov bx,-1 ;Return 0 (-1 + 1 = 0) fr_found: inc bx mov resseg, bx ;Return resident segment mov ax, 5803h ;Restore UMB link status pop bx int 21h pop es popa ret findres ENDP END start . 0