|
|
Programowanie Główna pascal Przechwytywanie przerwań i pisanie programów rezydentnych (TSR)
|
Przechwytywanie przerwań i pisanie programów rezydentnych (TSR) |
Powinieneś znać: Przerwania, Pamięć komputera Przerwanie jest to mówiąc w skrócie procedura zawarta w pamięci komputera z przyporządkowanym numerem od 00 do FFh. Mimo, ze może być ich nawet FF najczęściej używane są te do 30h. Sam DOS podczas ładowania przyporządkowuje im poszczególne procedury. I tak na przykład przerwanie 10h używane jest do zmiany trybów graficznych, a przerwanie 1Ch wskazuje na procedurę, którą zegar systemowy uruchamia 18 razy na sekundę. Czasami zdarza się, że musimy przechwycić jakieś przerwanie, czyli ustawić je tak, aby wykonywało naszą procedurę. Do czego to się przyda?
Zastosowanie 1 - wewnątrz naszego programu
Załóżmy, że piszesz program, który działa w trybie tekstowym i chcesz, aby non - stop w prawym górnym rogu ekranu widniała aktualna godzina. Gdybyś nie czytał tego mądrego tekstu to prawdopodobnie w setce miejsc w programie wstawiłbyś pokazywanie zegarka, co i tak byłoby zawodne. Zdecydowanie prościej jest przechwycić przerwanie 1Ch i 18 razy na sekundę wyświetlać zegarek w prawym górnym rogu ekranu. Gdy to zrobimy możemy normalnie pisać program, a system co chwila będzie odświeżać czasomierz, bez zbytnich zmian w programie! Jak to zrobić? Bardzo prosto. Najpierw powinniśmy napisać procedurę wyświetlającą zegarek. Nie powinna ona korzystać z write i innych tego typu funkcji (tak to już jest z procedurami podpinanymi pod przerwanie), więc najlepiej zrobimy, jeśli zegarek umieścimy od razu w pamięci komputera. Najpierw napiszmy procedurę stawiającą literę na ekranie:
1 2 3 4
| procedure Znak(x,y:integer;ch:char); begin Mem[$B800:120*(y-1)+x*2-2]:=Ord(Ch); end; |
(Jeśli nie rozumiesz tej procedury to nie martw się - nie ma większego znaczenia) Teraz pora zaprogramować zegarek. Procedurka jest banalna - pobiera czas systemowy, a następnie wyświetla godzinę.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| Uses DOS; {Tutaj wstaw procedure Znak} procedure Zegar; var h,m,s,s100:word; st:string; begin gettime(h,m,s,s100); str(h,st); Znak(69,1,'['); Znak(70,1,st[1]); ZNak(71,1,st[2]); Znak(72,1,':'); str(m,st); Znak(73,1,st[1]); ZNak(74,1,st[2]); Znak(75,1,':'); str(s,st); Znak(76,1,st[1]); ZNak(77,1,st[2]); Znak(78,1,']'); end; |
To jest dosyć oczywiste. Najpierw pobieramy czas do zmiennych h,m,s,s100, a następnie po kolei zamieniamy te zmienne na string i literka po literce wyświetlamy na ekranie. Zegarek wygląda ładnie, ale ma jedną wadę - nie rusza się. Gdybyś chciał napisać program, który działa i równocześnie wyświetla zegar to musiałbyś umieścić tą procedurę w pętli, lub coś w tym stylu. Jako, że jest to uciążliwe podepniemy ją pod przerwanie 1Ch, które wykonywane jest na tyle szybko, że zegarek będzie zawsze pokazywał odpowiedni czas. Jak to zrobimy? Przede wszystkim trzeba powiedzieć kompilatorowi, że procedura, którąą piszemy będzie podpięta pod przerwanie. Robimy to dodając słówko kluczowe interrupt po nazwie procedury:
1
| procedure Zegar;interrupt; |
Poza tym, kiedy chcemy przechwycić przerwanie musimy wydać odpowiednie polecenie. Jest to SetIntVec(X,Y) z modułu DOS. Parametr X oznacza numer przerwania (u nas $1C), a Y to wskaźnik do procedury (@Zegar):
1 2 3 4 5 6 7 8 9 10 11 12
| begin SetIntVec($1C,@Zegar); Writeln('Ten genialny program od tej pory będzie wywietlać godzinę systemową;'); Writeln('Niezależnie od tego, co będziemy robić. Np. Podczas readln:'); readln; Writeln('Czy delaya'); Delay(10000); Writeln('Raz przechwyciłe przerwanie i już nie musisz się nim przejmować!!!!'); readln; end. |
Przepisz teraz ten program, skompiluj go, obejrzyj wyniki, pozmieniaj co nieco (np. niech przy parzystych sekundach : zegarka się nie wyświetlał) i kiedy stwierdzisz, że znasz temat przejdź dalej..
Zastosowanie 2 - pisanie programów TSR (Terminate And Stay Resident)
Dawno, dawno temu, kiedy na Ziemi rządziły dinozaury nasi przodkowie korzystali z DOS'a. W tym oto systemie przechwytywanie przerwań miało dużo więcej zastosowań, niż dzisiaj. Otóż można było napisać programy, które mimo, że kończyły swoje działanie (system wracał do znaku zachęty C:>) siedziały nadal w pamięci, a dokładniej - procedury, które były podpięte pod przerwania zostawały w pamięci i taki np. zegarek z poprzedniego przykładu wyświetlał się nadal, nawet, jeśli były uruchamiane inne programy. Na tej zasadzie działała większość wirusów (podpinały się pod przerwanie zapisujące dane do pliku), sterowniki do myszek itp. W dzisiejszych czasach jest to praktycznie bezużyteczna technologia, gdyż pod Windowsem przerwań się praktycznie nie używa, ale mimo wszystko czasem się przydaje. Aby pozostawić program w pamięci powinieneś po przechwyceniu wszystkich przerwań wywołać polecenie Keep(0);. Zadziała ono podobnie do Halt, ale przerwania pozostaną w pamięci komputera. Jest to jednak w dobie Windowsa dosyć nieprzydatne zagadnienie..
|
|