Kurs Assemblera cz. 8

O SKUTECZNYM PRZERWAŃ SPOSOBIE

Komputer podczas pracy jest podobny do… bo ja wiem, bibliotekarza? Sekretarki? Kancelisty? W każdym razie do kogoś wykonującego zawód, który nie wymaga zbyt wiele twórczego myślenia. Oczywiście – jakiekolwiek tego typu porównanie będzie z definicji nieścisłe. Każde, nawet najbardziej nudne zajęcie wymaga czasem choć odrobiny myślenia twórczego. Na przykład bibliotekarz – wydawałoby się, że tylko przyjmuje, wypożycza i układa na półkach książki. I to wszystko. Ale co zdarzy się, gdy do biblioteki wpadnie groźny szaleniec z odbezpieczonym kałaszem? Komputer na stanowisku bibliotekarza zapewne spytałby delikwenta, czy może potrzebna mu książka na temat militariów z byłego Związku Sowieckiego. Człowiek zaś musiałby coś wykombinować, żeby jakoś się z tej sytuacji wyplątać (niewykluczone zresztą, że mimo wszystko nie znalazłby żadnego rozsądnego wyjścia, ale to nie należy do sprawy).

No dobrze, przejdźmy teraz do właściwej treści dzisiejszego odcinka, tj. do przerwań. Wiemy, że każdą, wykonywaną przez człowieka pracę można PRZERWAĆ. Wyobraź sobie, że odrabiasz właśnie lekcje, klnąc cicho profesorów za zbyt wiele zadań. Nagle dzwoni telefon. Nikogo innego w mieszkaniu nie ma. Co więc robisz? Z ulgą PRZERYWASZ pracę i przystępujesz do omówienia kwestii pójścia do kina na MCMLXXVI część Akademii Policyjnej. Gdy już dokładnie ustalisz szczegóły, odkładasz słuchawkę, POWRACASZ Z PRZERWANIA i kontynuujesz przygotowania do obrony pracy domowej.

W podobny sposób działa Twój komputer. Jego praca jest stosunkowo często PRZERYWANA (z reguły co 1/50 sekundy). Podczas takiej przerwy komputer zwykle sprawdza, czy ktoś aby nie nacisnął któregoś z klawiszy, mruga kursorem, przesuwa zegar i robi inne, podobnie fascynujące rzeczy. Po wykonaniu tych wszystkich arcyciekawych czynności POWRACA do programu, który wykonywał poprzednio. I wszystko gra, jak w orkiestrze strażackiej.

Znaleźli się jednak cwaniacy, którym taki obraz działania wszechświata nie do końca wystarczał. Mówili: „Przecież ten kursor nie może tak migać, zróbmy coś!” Albo: „Dlaczego klawisze nie pikają przy naciskaniu, jak w maszynach profesjonalnych (np. ZX SPECTRUM…)?” Naprzeciw tym, niewątpliwie słusznym, żądaniom wyszli twórcy układu 6502 i… odpowiednio go zaprojektowali. Dzięki temu każdy, kto jako tako potrafi posługiwać się asemblerem (tak, tak! To właśnie TY!), może dowolnie zmieniać procedury obsługi przerwań (tak mądrzy ludzie nazwali to, co komputer robi w przerwaniu).

Spróbujmy więc zrobić z przerwaniami coś pozytywnego. I to najlepiej tak, by można było przy okazji pisać jakiś program w BASIC-u. O, mam już pomysł. Niech w lewym górnym rogu pojawi się jakiś napis. I jeśli ten napis będzie się pojawiał co 1/50 sekundy, ciężko będzie go skasować. Ba! Nawet jeśli komuś się to uda, napis ten pojawi się znowu, za dokładnie 1/50 s! Dobre, co? Wpisz więc taki oto program:

(UWAGA! Jeśli używasz któregoś z modułów FINAL, to wyłącz go instrukcją KILL)

Uruchom program znajomą instrukcją SYS 10000. Jeśli coś nie działa, to na wszelki wypadek odłącz swój moduł (nawet, jeśli nie jest FINAL’em). Na ekranie pokazał się napis „ROBIN HOOD” (a wiecie dlaczego? Bo nie YAD!). Jakiekolwiek próby skasowania tego napisu skazane są na niepowodzenie. Uczynić to można jedynie kombinacją klawiszy RUN STOP/RESTORE, przyciskiem RESET, wyłącznikiem zasilania lub przez wyciągnięcie wtyczki z kontaktu.

Dlaczego jednak TO działa? Popatrzmy. Na początku pojawia się tajemniczy rozkaz SEI. Odłóżmy go na chwilkę na bok. Co robimy dalej? Bierzemy młodszy bajt adresu początku procedury, którą nazwałem „IRQ2”, a która zaczyna się od adresu $271d, i wstawiamy go do komórki $0314. Następnie starszy bajt tego adresu wstawiamy do komórki $0315. Komórki $0314/$0315 mają w systemie operacyjnym C-64 specyficzną rolę. Zawierają bowiem adres, do którego komputer ma skoczyć każdorazowo po przyjęciu przerwania typu IRQ. Adres ten przedstawiamy w postaci młodszego i starszego bajtu, tak jak na przykładzie. Czyli, jeśli praca procesora zostanie przerwana przerwaniem IRO, procesor skoczy do naszej procedury IR02, znajdującej się pod adresem $271d. Wszystko jasne?

Teraz wróćmy do tajemniczego rozkazu SEI („SEt Interrupt mask” – włącz maskę przerwań). Rozkaz ten powoduje, że komputer nie przyjmuje przerwań IRQ. Po prostu te przerwania nie są wykonywane. Powoduje to flaga I, nazywana też maską przerwań. Tak długo, jak maska ta jest włączona, żadne IRQ nie będą dla komputera na tyle ważne, by przerywać pracę nad programem, który aktualnie wykonuje. W naszym porównaniu pracy komputera do odrabiania lekcji, maskowanie przerwań da się przedstawić jako wyciągnięcie wtyczki telefonu z kontaktu. Od tej pory każdy może dzwonić do woli, my i tak będziemy robić swoje. Przerwania IRQ wyłączam nie bez powodu. Zaraz po wyłączeniu przerwań zmieniamy wektor IRQ, czyli adres, do którego procesor skacze po przyjęciu przerwania. Może się bowiem zdarzyć, że przerwanie zostanie zgłoszone PO wstawieniu nowej wartości do $0314 a PRZED wstawieniem naszej liczby do $0315. (A dlaczego nie? Przecież przerwania IRQ powtarzają się co 1/50 s. Prawdopodobieństwo nie jest więc duże, ale po co ryzykować.). I co się wtedy stanie? Zwykle wektor przerwań wskazuje na adres $ea31. My zaś zmieniamy tylko młodszy jego bajt, na $1d. Komputer skoczy więc do $eaid, czyli w jakieś maliny, w których znaleźć się nie powinien. Natknie się tam na jakieś głupie RTS i – jak to mówią starzy wyjadacze – się powiesi. Wyłączenie przerwań na ten krytyczny moment jest więc racjonalne i ze wszechmiar uzasadnione. Zwłaszcza, że i tak po ponownym, poprawnym ustawieniu wektora wydajemy rozkaz CLI („CLear Interrupt mask” – wyłącz maskę przerwań). CLI zezwala na ponowne uruchomienie IRQ.

Na tym kończymy program. Pozostaje tylko RTS, by powrócić do BASIC- a. W BASIC-u możesz swobodnie działać, pisać programy, nagrywać, ładować programy i robić, co tylko dusza zapragnie. „ROBIN HOOD” przetrwa wszystkie te próby i straszyć będzie nadal. Zaszkodzić mu może jedynie władowanie jakiegoś programu, który zajmie komórki o adresach 10000 – 10050. Tam bowiem siedzi nasza procedura. Wykonuje się ona co 1/50 s, więc władowanie w jej miejsce jakiegokolwiek innego programu spowoduje niechybne wpadnięcie komputera w maliny i powieszenie z rozpaczy.

Procedura IRQ2 to banalne wyświetlenie tekstu na ekranie. Nie wyma żadnego komentarza. Może tylko kończący ją rozkaz JMP $ea31, a nie jak zwykle, RTS albo BRK. Powoduje on skok do zwykłej procedury obsługi przerwań IRQ. Komputer robi tam swoje.

Nie każdy wie, że naciśnięcie klawisza RESTORE to także przerwanie. W odróżnieniu od IRQ, najczęściej nie jest wywoływane przez zegar, ani żadne inne czynniki wewnętrzne. Przerwanie to zgłaszasz Ty sam tłukąc w klawisz, najczęściej w połączeniu z klawiszem RUN/STOP. Powoduje to wystanie wprost do procesora impulsu wywołującego przerwanie NMI (Non-Maskable Interrupt – przerwanie niemaskowalne). Komputer zwykle sprawdza, czy naciśnięty został drugi klawisz z „fantastycznej dwójki” i jeśli tak, to wykonuje procedurę tzw. ciepłego startu: wszystkie kolory ustawia na standardowe, likwiduje duszki, wyłącza SID itd. Ma też to do siebie, że przerywa działanie programu BASIC-owego nie czyniąc w nim żadnych zmian. Dlatego dla piszących w BASIC-u jest zmorą. Dla nas, speców od asemblera, zmorą nie będzie, a czasem nawet może się przydać. Dla ułatwienia podpowiem, że wektor przerwania NMI to komórki $0318/$0319. One wskazują adres, pod który trzeba skoczyć po przyjęciu każdego przerwania NMI. Wpisz więc taki oto programik:

Programik ten jest, szczęśliwie, jeszcze krótszy od poprzedniego. Ko mentarz ograniczę do rzeczy niezbędnych. Nie wstawiłem rozkazów SEI i CLI, bo przerwania NMI są niemaskowalne – taka już ich natura. Jeśli zdążysz nacisnąć RESTORE po przestawieniu młodszego bajta, a przed przestawieniem starszego – twoja wina, twoja strata. Procedurka NMI2 jest króciutka – zmieniamy tylko kolor ramki we wszystkim znanej komórce $d020 (jeżeli nie wszystkim – odsyłam do mapy pamięci!). Zaraz potem występuje tajemniczy jeszcze rozkaz RTI. Aby rozwiać jego tajemniczość podaję, że oznacza on „ReTurn from Interrupt”, czyli „powróć z przerwania”. Jego wykonanie spowoduje powrót do wykonywania uczciwej pracy czyli tego, co siedzi w programie. Tu jeszcze jedna ważna wiadomość. Je żeli przerwiesz przerwanie IRQ, komputer nie straci głowy, lecz spokojnie wykona przerwanie NMI, powróci za pomocą RTI do przerwania IRQ, a z niego – do programu, który leży „na dnie”.

Na temat przerwań można by jeszcze pisać długo i szczęśliwie. Na początek jednak ta dawka teorii jest całkowicie wystarczająca. Już niedługo będzie interfejs do Pamiętnika Artylerzysty, czyli o przerwaniach rastra to i owo, lecz z nieco innej strony. Wasz Niezmordowany Płaskokrążek Informacjonośno-Stołokulotoczny BARTEK KACHNIARZ

Dziś poznaliśmy rozkazy:
SEI – włączenie maski przerwań, czyli zakaz wywoływania przerwań IRQ

CLI – wyłączenie maski przerwań, czyli unieważnienie zakazu wykonywania przerwań IRQ

RTI – powrót z przerwania do miejsca, w którym program został przerwany

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *