Program rezydentny (ang. TSR) tj. pozostający w pamięci komputera podczas normalnej pracy systemu i generujący jakiś ciekawy krótki dźwięk po naciśnięciu klawisza SPACE przy wciśniętym wcześniej klawiszu CTRL. Dźwięk jest generowany na głośniku PC (brzęczyku PC)
Program powinien się instalować w pamięci tylko jeden raz! Ponowne jego uruchomienie powinno generować komunikat, że program jest już zainstalowany.
Wywołanie programu z opcją -u odinstalowuje program i zwalnia zajmowaną przez niego pamięć
; by Pawel Konieczny
; ver 0.9
.model tiny
;..................................................
;ASSUME cs:code1, ds:code1
;................. Segment kodu ...................
code1 segment
org 100h
start:
jmp param
stproc dd 0
znacznik dw 'vs'
czasomierz equ 40h
TC equ 36157 ; 1193181Hz/33Hz
TD equ 32248 ; 1193181Hz/37Hz
TE equ 29102 ; 1193181Hz/41Hz
TF equ 27118 ; 1193181Hz/44Hz
TG equ 24351 ; 1193181Hz/49Hz
TA equ 21694 ; 1193181Hz/55Hz
TH equ 19245 ; 1193181Hz/62Hz
; -------------------------------------------------
; Glowny kod programu
; -------------------------------------------------
mainprog:
push es
in al,60h ;pobierz klawisz
cmp al,39h ;scan-code spacji
jne koniec
xor ax,ax
mov es,ax
test byte ptr es:[417h],4 ;sprawdzam czy jest 'ctrl' wcisniety
jz koniec
; wlaczenie
in al,61h ; czyta biezacy status kontrolera
or al,00000011b ; dwa ostatnie bity na '1'
out 61h,al ; zapisuje nowy status
; melodia
mov ax,TA ; 1193181 / czestotl. = ax
mov cl,3
shr ax,cl ; ax = ax / 2^oktawa
call graj
call czas
mov ax,TC
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TH
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TC
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
; -------------------
mov ax,TE
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TG
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TE
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TD
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TE
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TE
mov cl,4
shr ax,cl
call graj
call czas
; ------------------
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TC
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TD
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TH
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TH
mov cl,3
shr ax,cl
call graj
call czas
; --------------------
mov ax,TC
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TG
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TH
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
; wylaczenie
in al,61h ; czyta biezacy status kontrolera
and al,11111100b ; dwa ostatnie buty na '0'
out 61h,al ; zapisuje nowy status
jmp koniec
sek PROC
mov cx,0fh
mov dx,4240h
ret
sek ENDP
pol_sek PROC
mov cx,7Ah
mov dx,120h
ret
pol_sek ENDP
cw_sek PROC
mov cx,3Dh
mov dx,090h
ret
cw_sek ENDP
os_sek PROC
mov cx,1Eh
mov dx,848h
ret
os_sek ENDP
graj PROC ; ax - podzielnik
out 42h,al
mov al,ah
out 42h,al
ret
graj ENDP
czas PROC
xor al,al ;opoznienie na 1 sek
out 70h,al ;czas odczytuje z cmosu
jmp $+2 ;drobne opuznienie potrzebne do poprawnej wspolpracy z CMOS
in al,71h
mov dl,al
petla1: ;w tej petli pobieram aktualna sekunde
xor al,al
out 70h,al
jmp $+2 ;drobne opoznienie potrzebne do poprawnej wspolpracy z CMOS
in al,71h
cmp dl,al ;i sprawdzam czy jest rowna poprzedniej
je petla1
ret
czas ENDP
koniec:
pop es
jmp dword ptr cs:[stproc] ; skok do oryginalnej procedury
; -------------------------------------------------
; Wczytywanie parametru
; -------------------------------------------------
param:
mov ax,cs
mov ds,ax ; DS = CS, na wszelki wypadek
mov al,byte ptr es:[80h]
cmp al,0
je install
mov al,byte ptr es:[81h] ; sprawdzamy kolejny znak w linii polecen
cmp al,0dh
je install ; Enter = koniec linii, wiec instaluj
mov al,byte ptr es:[82h]
cmp al,'-'
jne Komunikat1
mov al,byte ptr es:[83h]
cmp al,'u'
jne Komunikat1
mov al,byte ptr es:[84h]
cmp al,0dh
jne Komunikat1
jmp uninstall
; -------------------------------------------------
; Odinstalowanie
; -------------------------------------------------
Uninstall:
mov ax,3508h ; pobranie wektora przerwania
int 21h
cmp bx,offset mainprog ; sprawdzamy, czy sie zgadzaja offsety
jne NieMa
;mov si,offset znacznik ; adres lokalnego znacznika do DS:SI
;mov di,si ; i znacznika sprawdzanego do ES:DI
;mov cx,2 ; dlugosc znacznika w bajtach
;cld
;repe cmpsb ; sprawdzamy az do rozniacego sie bajtu
mov si,'vs'
mov di,si
cmp word ptr es:[bx-2],'vs'
jne NieMa ; gdy rozne znaczniki
;jnz NieMa
mov dx,word ptr es:[stproc] ; czytamy oryginalny wektor
mov ax,word ptr es:[stproc+2] ; z bloku TSRa
mov ds,ax
mov ax,2508h ; ustawienie wektora przerwania, adres podany w ds:dx
int 21h
mov ah,49h ; zwolnienie bloku pamieci w segmencie ES z TSRem
int 21h
mov ax,cs
mov ds,ax ; przywracamy do DS segment naszego programu
mov ah,9 ; wydruk napisu na ekran
mov dx,offset uninst
int 21h ; drukujemy komunikat o pomylym usuniêciu TSRa
jmp koniecx
NieMa:
mov ah,9 ; wydruk napisu na ekran
mov dx,offset blad
int 21h
jmp koniecx
; -------------------------------------------------
; Instalowanie
; -------------------------------------------------
Install:
mov ax,3508h
int 21h ; sprawdz, czy przed procedura obslugi przerwania ...
cmp word ptr es:[bx-2],'vs' ; ... znajduje sie 'vs'
je Komunikat2 ; jesli tak, to znak, ze program byl juz zainstalowany
mov es,word ptr ds:[2ch] ; numer segmentu srodowiska odczytamy z PSP, wrzucimy do ES
mov ah,49h ; zwolnienie bloku pamieci
int 21h
mov ax,3508h ; pobranie adresu procedury obslugi przerwania 8h
int 21h ; wynik do ES:BX
mov word ptr cs:[stproc],bx
mov word ptr cs:[stproc+2],es
mov ax,2508h ; ustawienie nowego adresu procedury obslugi przerwania
mov dx,offset mainprog ; DS:DX - wektor naszej procedury
int 21h
mov ah,9 ; wydruk napisu na ekran
mov dx,offset inst
int 21h
mov dx,offset param ; do DX wpisujemy adres pierwszego bajtu, który ma byc zwolniony
int 27h ; wczesniejsze pozostaja pamieci
; -------------------------------------------------
; Reszta kodu
; -------------------------------------------------
Komunikat1:
lea dx,error_1
jmp sh_err
Komunikat2:
lea dx,error_2
jmp sh_err
sh_err: ; wypisuje na ekran bledy
mov ah,9h
int 21h
koniecx:
mov ax,4c00h
int 21h
error_1 db 'Bledny parametr$'
blad db 'Nie mozna odinstalowac programu, ktory nie byl zainstalowany$'
uninst db 'Program odinstalowano.$'
error_2 db 'Program byl juz wczesniej zainstalowany.$'
inst db 'Program zainstalowano.$'
code1 ends
;..................................................
END start
; ver 0.9
.model tiny
;..................................................
;ASSUME cs:code1, ds:code1
;................. Segment kodu ...................
code1 segment
org 100h
start:
jmp param
stproc dd 0
znacznik dw 'vs'
czasomierz equ 40h
TC equ 36157 ; 1193181Hz/33Hz
TD equ 32248 ; 1193181Hz/37Hz
TE equ 29102 ; 1193181Hz/41Hz
TF equ 27118 ; 1193181Hz/44Hz
TG equ 24351 ; 1193181Hz/49Hz
TA equ 21694 ; 1193181Hz/55Hz
TH equ 19245 ; 1193181Hz/62Hz
; -------------------------------------------------
; Glowny kod programu
; -------------------------------------------------
mainprog:
push es
in al,60h ;pobierz klawisz
cmp al,39h ;scan-code spacji
jne koniec
xor ax,ax
mov es,ax
test byte ptr es:[417h],4 ;sprawdzam czy jest 'ctrl' wcisniety
jz koniec
; wlaczenie
in al,61h ; czyta biezacy status kontrolera
or al,00000011b ; dwa ostatnie bity na '1'
out 61h,al ; zapisuje nowy status
; melodia
mov ax,TA ; 1193181 / czestotl. = ax
mov cl,3
shr ax,cl ; ax = ax / 2^oktawa
call graj
call czas
mov ax,TC
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TH
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TC
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
; -------------------
mov ax,TE
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TG
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TE
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TD
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TE
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TE
mov cl,4
shr ax,cl
call graj
call czas
; ------------------
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TC
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TD
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TH
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TH
mov cl,3
shr ax,cl
call graj
call czas
; --------------------
mov ax,TC
mov cl,4
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TG
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TH
mov cl,3
shr ax,cl
call graj
call czas
mov ax,TA
mov cl,3
shr ax,cl
call graj
call czas
; wylaczenie
in al,61h ; czyta biezacy status kontrolera
and al,11111100b ; dwa ostatnie buty na '0'
out 61h,al ; zapisuje nowy status
jmp koniec
sek PROC
mov cx,0fh
mov dx,4240h
ret
sek ENDP
pol_sek PROC
mov cx,7Ah
mov dx,120h
ret
pol_sek ENDP
cw_sek PROC
mov cx,3Dh
mov dx,090h
ret
cw_sek ENDP
os_sek PROC
mov cx,1Eh
mov dx,848h
ret
os_sek ENDP
graj PROC ; ax - podzielnik
out 42h,al
mov al,ah
out 42h,al
ret
graj ENDP
czas PROC
xor al,al ;opoznienie na 1 sek
out 70h,al ;czas odczytuje z cmosu
jmp $+2 ;drobne opuznienie potrzebne do poprawnej wspolpracy z CMOS
in al,71h
mov dl,al
petla1: ;w tej petli pobieram aktualna sekunde
xor al,al
out 70h,al
jmp $+2 ;drobne opoznienie potrzebne do poprawnej wspolpracy z CMOS
in al,71h
cmp dl,al ;i sprawdzam czy jest rowna poprzedniej
je petla1
ret
czas ENDP
koniec:
pop es
jmp dword ptr cs:[stproc] ; skok do oryginalnej procedury
; -------------------------------------------------
; Wczytywanie parametru
; -------------------------------------------------
param:
mov ax,cs
mov ds,ax ; DS = CS, na wszelki wypadek
mov al,byte ptr es:[80h]
cmp al,0
je install
mov al,byte ptr es:[81h] ; sprawdzamy kolejny znak w linii polecen
cmp al,0dh
je install ; Enter = koniec linii, wiec instaluj
mov al,byte ptr es:[82h]
cmp al,'-'
jne Komunikat1
mov al,byte ptr es:[83h]
cmp al,'u'
jne Komunikat1
mov al,byte ptr es:[84h]
cmp al,0dh
jne Komunikat1
jmp uninstall
; -------------------------------------------------
; Odinstalowanie
; -------------------------------------------------
Uninstall:
mov ax,3508h ; pobranie wektora przerwania
int 21h
cmp bx,offset mainprog ; sprawdzamy, czy sie zgadzaja offsety
jne NieMa
;mov si,offset znacznik ; adres lokalnego znacznika do DS:SI
;mov di,si ; i znacznika sprawdzanego do ES:DI
;mov cx,2 ; dlugosc znacznika w bajtach
;cld
;repe cmpsb ; sprawdzamy az do rozniacego sie bajtu
mov si,'vs'
mov di,si
cmp word ptr es:[bx-2],'vs'
jne NieMa ; gdy rozne znaczniki
;jnz NieMa
mov dx,word ptr es:[stproc] ; czytamy oryginalny wektor
mov ax,word ptr es:[stproc+2] ; z bloku TSRa
mov ds,ax
mov ax,2508h ; ustawienie wektora przerwania, adres podany w ds:dx
int 21h
mov ah,49h ; zwolnienie bloku pamieci w segmencie ES z TSRem
int 21h
mov ax,cs
mov ds,ax ; przywracamy do DS segment naszego programu
mov ah,9 ; wydruk napisu na ekran
mov dx,offset uninst
int 21h ; drukujemy komunikat o pomylym usuniêciu TSRa
jmp koniecx
NieMa:
mov ah,9 ; wydruk napisu na ekran
mov dx,offset blad
int 21h
jmp koniecx
; -------------------------------------------------
; Instalowanie
; -------------------------------------------------
Install:
mov ax,3508h
int 21h ; sprawdz, czy przed procedura obslugi przerwania ...
cmp word ptr es:[bx-2],'vs' ; ... znajduje sie 'vs'
je Komunikat2 ; jesli tak, to znak, ze program byl juz zainstalowany
mov es,word ptr ds:[2ch] ; numer segmentu srodowiska odczytamy z PSP, wrzucimy do ES
mov ah,49h ; zwolnienie bloku pamieci
int 21h
mov ax,3508h ; pobranie adresu procedury obslugi przerwania 8h
int 21h ; wynik do ES:BX
mov word ptr cs:[stproc],bx
mov word ptr cs:[stproc+2],es
mov ax,2508h ; ustawienie nowego adresu procedury obslugi przerwania
mov dx,offset mainprog ; DS:DX - wektor naszej procedury
int 21h
mov ah,9 ; wydruk napisu na ekran
mov dx,offset inst
int 21h
mov dx,offset param ; do DX wpisujemy adres pierwszego bajtu, który ma byc zwolniony
int 27h ; wczesniejsze pozostaja pamieci
; -------------------------------------------------
; Reszta kodu
; -------------------------------------------------
Komunikat1:
lea dx,error_1
jmp sh_err
Komunikat2:
lea dx,error_2
jmp sh_err
sh_err: ; wypisuje na ekran bledy
mov ah,9h
int 21h
koniecx:
mov ax,4c00h
int 21h
error_1 db 'Bledny parametr$'
blad db 'Nie mozna odinstalowac programu, ktory nie byl zainstalowany$'
uninst db 'Program odinstalowano.$'
error_2 db 'Program byl juz wczesniej zainstalowany.$'
inst db 'Program zainstalowano.$'
code1 ends
;..................................................
END start