plik


MINI KURS PISANIA PROGRAMÓW TSR W ASEMBLERZE 4. WADY I ZALETY MULTIPLEX INTERRUPT Na początku wyjaśnijmy sobie o co w ogóle chodzi w tytule tej części. Otóż Multiplex Interrupt jest to jedno z przerwań programowych (to znaczy nie wywoływanych przez sprzęt, jak np. przerwanie zegara, ale tylko poprzez instrukcję int). Ma numer 2fh i służy do bardzo wielu przydatnych rzeczy a w szczególności niesie pomoc w programach rezydentnych. Cała istota Multiplex Interrupt (w skrócie MxI) polega na utworzeniu "łańcucha", do którego dopinają się kolejne programy wykorzystujące je - TSRy. Każdy program ma przydzielony swój numer identyfikacyjny, po którym może poznać, czy odwołanie MxI dotyczy tego rezydenta, czy jakiegoś innego. W trakcie instalacji TSR odczytuje wektor przerwania 2fh i ustawia nowy na swoją procedurę. Teraz kiedy przyjdzie przerwanie i w rejestrze AH jest jego numer identyfikacyjny to oznacza, że do niego przyszło zlecenie (o tym będzie dalej) i on je ma obsłużyć. Jeżeli w AH jest inny numer, TSR przekazuje sterowanie pod stary adres (zapamiętany podczas instalacji). Powyższe tłumaczenie jest dość zawiłe, dlatego podam trochę konkretów: Przerwanie 2Fh Nazwa: Obsługa równoczesnych procesów Wywołanie: AH = numer procesu (czyli ID TSRa) 01h - rezydentna część polecenia PRINT 02h - rezydentna część polecenia ASSIGN 03h - rezydentna część polecenia SHARE 80h-0ffh - dostępne dla innych procesów AL = 0 Powrót: AL - stan zainstalowania 00h - nie zainstalowany, można zainstalować 01h - nie zainstalowany, nie można zainstalować 0ffh - zainstalowany Opis: Przerwanie organizuje równoczesną pracę programów rezydentnych dostępnych z dowolnego procesu. Pierwotnie dotyczyło tylko polecenia systemowego PRINT. Każdy proces instaluje się w kolejce (poprzez kolejne przechwytywanie tego przerwania). W przypadku wywołania zlecenia proces sprawdza, czy zlecenie go dotyczy, jeśli nie to oddaje sterowanie poprzedniemu w kolejce. W rejestrze AL przekazywany jest kod zlecenia. Standardowo zlecenie numer 0 oznacza pytanie o to, czy program jest zainstalowany. Z powyższego opisu widzimy, jak prosta jest zasada działania MxI, wszystkie rezydentne polecenia DOSu mają wbudowaną obsługę swoich funkcji przez to przerwanie (np. możemy poleceniu PRINT kazać zatrzymać wszystkie wydruki znając numer zlecenia, które mamy mu przekazać), na przykład: mov ax,0103h ; 01-PRINT, 03-zatrzymanie drukowania int 2fh Działanie Multiplex Interrupt w naszym rezydencie zależy tylko od naszej inwencji, poza oczywiście zleceniem nr 0, które ma przekazać informację o zainstalowaniu programu. Wtedy możemy stwierdzić, czy TSR jest obecny w pamięci, pomimo że po nim był instalowany inny program rezydentny, który również przechwycił to samo przerwanie (w przypadku sekundnika przerwanie zegara). Poza tym możemy dodać również nasze nowe zlecenia, np. zmiana kolorów cyfr bez reinstalacji programu, podawanie segmentu, w którym jest obecny kod TSRa i tak dalej. Przykładów można znaleźć bez liku, jeśli tylko dysponuje się rozwiniętą wyobraźnią. W naszym nowym przykładowym rezydencie (ile razy można obrabiać i ulepszać sekundnik?) zastosujemy procedurę, która będzie "wrażliwa" na ID procesu nr 90h (dlaczego tak? wymyśliło mi się, można podać numer od 80h w górę) i zlecenia nr 0 oraz 1. Czasem takie założenia mogą nie przynieść spodziewanych rezultatów, gdy w pamięci będzie inny TSR reagujący również na numer 90h - przy takich obawach można napisać funkcję przeszukującą kolejne numery od 80h (sprawdzamy zleceniem 0, czy rezydent jest zainstalowany) i zatrzymującą się na pierwszym wolnym. My jednak przyjmiemy, że 90h jest dla nas wystarczający i nic się nie powtórzy. Zlecenie nr 0 będzie służyło do sprawdzania, czy nasz rezydent jest obecny w pamięci (czyli będziemy w AL zwracać 0ffh) oraz przy okazji czytania numeru segmentu, w jakim jest on zainstalowany (zwracamy w BX). Natomiast zlecenie nr 1 będzie nam podawać w ES:DI adres ciągu znaków (zakończonego znakiem dolara, tak jak w napisach w DOSie) z wersją zainstalowanego TSRa. Sam program rezydentny będzie realizował trywialne zadanie - podepniemy go pod przerwanie klawiatury i przy każdym naciśnięciu klawisza będzie generowany dźwięk o długości zależnej od czasu naciśnięcia (czyli po stwierdzeniu naciśnięcia włączymy dźwięk PC Speakera, a przy puszczeniu wyłączymy). Do tego będzie jeszcze aktywna kombinacja Alt-Ctrl-Ins, przełączająca nam dźwięk (na zasadzie włączony - wyłączony - włączony itd). I znów to samo - sam program nie jest przeznaczony do używania w konkretnych celach (czy sekundnik komuś się do czegoś przydał?), ale do zobrazowania technik pisania TSRów. Przy usuwaniu programu rezydentnego z pamięci (nazwijmy go roboczo: beep) należy pamiętać o sprawdzeniu MxI, czy TSR jest obecny, jak również o odczytaniu wektora przerwania klawiatury (int 9h), ponieważ nie możemy usunąć TSRa i odtworzyć wykorzystywanych przez niego przerwań, kiedy po nim został zainstalowany inny rezydent (bo w ten sposób odcięlibyśmy od "funkcji życiowych" również ten inny program). Jednak jest na to sposób - odcinamy tylko działanie kliku i kombinacji Alt-Ctrl-Ins poprzez ustawienie odpowiedniej flagi w obszarze TSRa (można by było też po to wymyślić nowe zlecenie MxI, ale po co kombinować, gdy po odczytaniu numeru segmentu kodu zleceniem 0 mamy dostęp do obszaru zmiennych beepa), nazywa się ona 'niemamnie' i gdy nie jest równa 0 to TSR zachowuje się tak, jakby go w ogóle nie było. Gdyby beep rezerwował sobie dodatkowe bloki pamięci należało by je również zwolnić. Pamiętajmy również o tym, aby w czasie instalacji sprawdzić, czy przypadkiem już wcześniej beep nie był instalowany, a jeżeli tak - wyświetlić stosowny komunikat, no i oczywiście zwolnić blok pamięci zajmowany przez środowisko programu. Nasz TSR nie będzie tym razem sprawdzał parametrów podanych w linii poleceń w poszukiwaniu 'u', natomiast po uruchomieniu będzie się instalował w pamięci, a po powtórnym uruchomieniu - usuwał (lub dezaktywował). Po wywołaniu przez system przerwania klawiatury, pod które jesteśmy podpięci możemy odczytać kod wciśniętego klawisza z portu 60h (in al,60h), jest to tzw. scan-code klawisza, czyli najogólniej mówiąc jego kolejny numer na klawiaturze. Klawisz Insert ma scan-code równy 52h, natomiast ten sam klawisz przy zwolnieniu wysyła kod o 80h większy (z ustawionym najwyższym bitem), czyli 0d2h. Klawiatura rozszerzona 101-klawiszowa wysyła ponadto dodatkowe kody informujące, czy naciśnięto Ins z klawiatury numerycznej, czy szary Ins z dodatkowego bloku - jest wtedy przed scan-code klawisza Insert wysyłany kod 0e0h - my po odebraniu takiego kodu przekazujemy sterowanie bezpośrednio do oryginalnej procedury. W programie beep będziemy reagować na puszczenie klawisza Insert ze względu na samopowtarzanie przy dłuższym naciśnięciu (gdyby TSR reagował na naciśnięcie, obserwowalibyśmy naprzemienne włączanie i wyłączanie funkcji programu). Fakt wciśnięcia jednocześnie Alt i Ctrl rozpoznamy badając obszar zmiennych BIOSu (komórka 0:417h, bity 2 i 3 ustawione, traktowała o tym szerzej część 3 kursu). Po rozpoznaniu "korzystnej" kombinacji (Alt-Ctrl-Ins) zmieniamy wartość wewnętrznego przełącznika (zmienna flipflop), po czym zwracamy sterowanie do oryginalnej procedury obsługi przerwania klawiatury. Gdybyśmy nie chcieli tego robić (np. przechwycić i "zdusić" wszystkie naciśnięcia klawisza X) i nie przesyłać sterowania pod oryginalny adres (czyli do poprzedniego programu dołączonego do int 9h, a w końcu do procedury w BIOSie wpisującej kod ASCII klawisza do bufora klawiatury), należałoby wykonać następujący fragment kodu, wymagany do poprawnego powrotu do głównego programu instrukcją iret: in al,61h ;+ znak dla kontrolera klawiatury, że zakończyliśmy mov ah,al ;+ obsługę przerwania or al,80h ;+ out 61h,al ;+ mov al,ah ;+ out 61h,al ;+ mov al,20h ;- znak dla kontrolera przerwań out 20h,al ;- (tzw. EOI - End Of Interrupt) Do włączania dźwięku w głośniku służą instrukcje: in al,61h or al,3 ; ustawiamy bity: 0 i 1 out 61h,al Do wyłączania: in al,61h and al,0fch ; zerujemy bity: 0 i 1 out 61h,al Na początku w trakcie instalacji TSRa możemy jeszcze ustawić wysokość dźwięku wysyłając 2 bajty wartości licznika do timera (który obsługuje i zegar, i generator głośnika). Wartość licznika to: 1193181/f, f - częstotliwość dźwięku. Z tego wynika, że chcąc ustawić wysokość dźwięku na 440 Hz należy ustawić licznik na 1193181/440 = 2712, czyli 0a98h. Wysyłamy kolejno: kod operacji (0b6h) do portu 43h, następnie młodszy bajt licznika (98h) do portu 42h, a potem starszy bajt (0ah): mov al,0b6h out 43h,al mov al,98h out 42h,al mov al,0ah out 42h,al W naszym przykładowym programie beep możliwość ustawienia wysokości dźwięku nie została wykorzystana, możecie to zrobić w swoich programach. Można też również pokusić się o napisanie rezydenta, który po każdym naciśniętym klawiszu będzie zmieniał wysokość tonu, biorąc ją na przykład z tablicy. Wtedy przy pisaniu tekstu komputer będzie grał muzykę! To tyle na dziś, zobaczymy, co przyniesie kolejny odcinek.

Wyszukiwarka

Podobne podstrony:
Asembler w TSR KURS2
Asembler w TSR KURS0
Asembler w TSR KURS5
Asembler w TSR KURS3
Asembler w TSR SPIS TRE
Asembler w TSR KURS1
Asembler linux
TASM operacje asembler
21 Pisanie i uruchamianie programĂłw w asemblerze
kurs4
Procedury arytmetyczne w języku Asembler ST7
OAK W11 Asembler Pentium
asembler
Asembler Podstawy programowania w Windows
Praktyczny kurs asemblera

więcej podobnych podstron