Program rezydentny

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 pomyœlym 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

Dodaj komentarz