Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

Autor artykułu: mgr Jerzy Wałaszek

©2024 mgr Jerzy Wałaszek
I LO w Tarnowie

obrazek

Przykładowa Maszyna Cyfrowa I

Operacje Wejścia/Wyjścia

SPIS TREŚCI
Podrozdziały
W rozdziale zajmuję się obsługą portów wejścia/wyjścia, które dla PMC są bramą do świata zewnętrznego. Poprzez porty we/wy program może komunikować się z użytkownikiem. PMC jest bardzo prosta i nie posiada zbyt wielu możliwości prezentacji informacji. Nie jest to żadne niedopatrzenie - moim celem była i jest wciąż względna prostota zastosowanych rozwiązań. Dzięki niej programowanie operacji na portach we/wy nie wymaga studiowania tomów instrukcji.

Wypisywanie dowolnego tekstu

Umówmy się na początku, iż teksty będziemy umieszczać w pamięci PMC ze specjalnym kodem o wartości 0 na końcu. Kod ten nazywa się znacznikiem końca tekstu. W PMC można to osiągnąć następująco:

         ...
TEKST:   DAT "Poznaj swój komputer"  ;właściwy tekst
         DAT 0                       ;znacznik końca tekstu
         ...

obrazek

Program odczytujący taki tekst z pamięci po natrafieniu na znak o kodzie 0 będzie wiedział, iż tekst się właśnie mu skończył. Znak zero można w prosty sposób przetestować poleceniem skoku warunkowego JZR.

Poniższy program wypisuje tekst powitalny na wyświetlaczu znakowym. Zasada działania jest bardzo prosta. Kolejne znaki tekstu pobierane są z pamięci przy pomocy polecenia LDA z trybem pośrednim z postinkrementacją. W trybie tym wykorzystywana jest jedna z komórek pamięci PMC do przechowywania adresu danych. Każde zaadresowanie powoduje pobranie danych z pamięci i zwiększenie ich adresu o 1, dzięki czemu wskazywane są kolejne dane (w naszym przypadku kolejne literki tekstu). Pobrany znak zostaje sprawdzony poleceniem JZR na wartość 0, która oznacza koniec tekstu. Jeśli nie jest to znak końca tekstu, to zostaje przesłany na wyświetlacz znakowy do portu CHP, a pozycja na wyświetlaczu w porcie CHI zostaje zwiększona.

        RUN START

TXT:    DAT "Witamy w PMC" ;tekst do wyświetlenia
        DAT 0              ;znacznik końca tekstu
TPTR:   DAT TXT            ;adres początku tekstu

START:  LDA (TPTR++)  ;pobieramy kolejny znak tekstu
        JZR #EX1      ;kończymy, jeśli kod zero
        STA CHP       ;przesyłamy na port znakowy
        INC CHI       ;zwiększamy pozycję na wyświetlaczu
        JMP #START
EX1:

obrazek

Tego typu program potrafi wyświetlać tylko krótkie teksty. Dłuższe spowodują nadpisanie informacji, ponieważ przekroczenie pozycji nr 15 na wyświetlaczu spowoduje przewinięcie się licznika pozycji CHI, który jest 4 bitowy. Innym sposobem prezentacji tekstu może być przewijanie w stylu reklamy lub napisów na giełdzie. W PMC można to w prosty sposób osiągnąć ustawiając na stałe pozycję wyświetlania w CHI na 15, a następnie przesyłanie znaku do CHP, po którym następuje przesłanie kodu kontrolnego o wartości 258. Kod ten powoduje przesunięcie w lewo wszystkich literek na wyświetlaczu z wpisaniem znaku spacji na ostatniej pozycji.

Poniższy program wyświetla w kółko zadany napis. Ponieważ wyświetlanie napisu jest powtarzane, to przed wejściem do pętli program ustawia na nowo adres tekstu w zmiennej wskaźnikowej TPTR. W pętli głównej wprowadziłem małą pętlę opóźniającą, aby tekst był czytelny na szybszym komputerze. W razie konieczności należy dostosować zawartość akumulatora.

        RUN START

TPTR:   DAT 0   ;tutaj będzie adres tekstu

TEKST:  DAT "W dzisiejszych rozgrywkach klas III w kategorii "
        DAT "programowania w języku Pascal pierwsze miejsce "
        DAT "zajęła klasa III J. Na miejscu drugim uplasowała "
        DAT "się klasa III A. Miejsce trzecie przypadło "
        DAT "w udziale klasie III C. GRATULUJEMY!"
        DAT "                "
        DAT 0   ;znacznik końca tekstu

START:  LDA #15      ;ustawiamy pozycję na wyświetlaczu
        STA CHI
LP1:    LDA #TEKST   ;ustawiamy adres początku testu
        STA TPTR
LP2:    LDA (TPTR++) ;pobieramy znak
        JZR #LP1     ;jeśli koniec, to od początku
        STA CHP      ;znak na wyświetlacz
        LDA #-10     ;pętla opóźniająca, powtarzana aż
LP3:    ADD #1       ;ACR osiągnie wartość 0
        JMI #LP3
        LDA #258     ;kod przesunięcia w lewo
        STA CHP
        JMP #LP2

Na początek:  podrozdziału   strony 

Odczyt tekstu

Tekst odczytujemy z portu INP. Brzmi to dosyć prosto, jednak w praktyce takie proste nie jest, ponieważ musimy obsłużyć kilka sytuacji, które mogą się zdarzyć w trakcie odczytu:

Z tego prostego przykładu możesz wyobrazić sobie złożoność operacji wejścia / wyjścia w prawdziwym systemie komputerowym, gdzie mogą wystąpić dodatkowe sytuacje (np. pełny dysk, błąd odczytu, zerwanie transmisji itp.).

Poniższy program obsługuje odczyt tekstu z portu INP. Odczytywany tekst wstawiony zostaje do tablicy o szesnastu elementach. Wielkość tablicy limituje długość tekstu do 15 znaków (dziesiąty znak to znak o kodzie 0). Jeśli użytkownik poda więcej znaków, to zostaną one odczytane, ale będą zignorowane i nie trafią do tablicy, w której będzie tylko pierwszych 15 znaków. Jeśli będzie ich mniej, to tablica nie zostanie zapełniona w całości. W każdym przypadku na końcu wczytanego tekstu zawsze umieszczany jest znak 0. Po wczytaniu tekstu zostanie on następnie wyprowadzony na wyświetlacz znakowy za pomocą metody opisanej w poprzednim rozdziale.

        RUN START

TPTR:   DAT TEXT   ;zmienna wskaźnikowa, przechowuje adres tekstu
TEXT:   DAT "0123456789ABCDEF" ;bufor dla tekstu - 16 znaków
I:      DAT 15     ;maksymalna liczba znaków do odczytu

START:  LDA INP      ;odczytujemy pierwszy znak
        JZR #START   ;bufor zajęty, czekamy
        JMI #START   ;bufor pusty, też czekamy
LP1:    STA (TPTR++) ;jest znak, umieszczamy go w buforze
        LDA I        ;sprawdzamy, czy bufor pełny, co stanie się,
        SUB #1       ;gdy licznik osiągnie zero
        STA I
        JZR #INPE    ;tak, kończymy odczyt
LP2:    LDA INP      ;czytamy kolejny znak
        JZR #LP2     ;jeśli bufor zajęty, to czekamy
        JMI #INPE    ;jeśli pusty, to kończymy odczyt
        JMP #LP1     ;inaczej wykonujemy kolejny obieg
INPE:   LDA INP      ;pozbywamy się reszty znaków
        JMI #EX1
        JMP #INPE
EX1:    LDA #0        ;na końcu tekstu umieszczamy kod 0
        STA (TPTR++)
        LDA #TEXT     ;odtwarzamy adres początku tekstu
        STA TPTR
LP3:    LDA (TPTR++)  ;wyświetlamy odczytany tekst
        JZR #0        ;znak końca tekstu, kończymy
        STA CHP       ;zwykły znak, wyświetlamy go
        INC CHI       ;następna pozycja
        JMP #LP3

Na początek:  podrozdziału   strony 

Wyświetlanie liczb

Program produkuje wyniki, które umieszcza w komórkach pamięci. W PMC możemy podglądnąć zawartość dowolnych komórek, nie istnieje więc konieczność wyprowadzania liczb na wyświetlacz. Jednak w prawdziwym komputerze opcja taka nie jest dostępna. Dlatego musimy poznać metody przekształcania wartości liczby na ciąg cyfr w wybranym systemie pozycyjnym. Teoretycznie zadanie to rozwiązaliśmy we wcześniejszych rozdziałach. Teraz nadszedł czas na część praktyczną.

Wyświetlanie liczb dziesiętnych bez znaku

Pierwszy program oblicza kolejne cyfry dziesiętne podanej liczby dodatniej z zakresu od 0 do 32767. Do obliczeń stosujemy odwrotny algorytm Hornera. Polega on na znajdowaniu reszty z dzielenia liczby przez 10. Reszty te tworzą cyfry od ostatniej do pierwszej. Po obliczeniu reszty liczbę należy podzielić przez 10. Obliczenia kontynuujemy aż do otrzymania liczby o wartości zero. Na przykład:

Liczba ma wartość 23756.

23756 :  10 =  2375 i reszta 6
2375 :  10 =  237 i reszta 5
237 :  10 =  23 i reszta 7
23 :  10 =  2 i reszta 3
2 :  10 =  0 i reszta 2

Reszta jest wartością liczbową od 0 do 9. Aby otrzymać kod znaku ASCII przedstawiającego odpowiednią cyfrę, należy do otrzymanej reszty dodać kod znaku "0" równy 48. Ponieważ otrzymujemy cyfry w kolejności odwrotnej, to będą one wstawiane do 6 elementowej tablicy począwszy od 5 elementu (piąty element ma indeks 4 - nie zapominaj o tym, to bardzo ważne!!!) w dół (maksymalnie może być 5 cyfr). Tablica jest wypełniona znakiem spacji przed rozpoczęciem obliczania cyfr. W szóstym elemencie przechowywany jest znak o kodzie 0. Po uzyskaniu cyfr liczba zostaje wyświetlona na wyświetlaczu znakowym.

        RUN START

N:      DAT 12654   ;liczba do wyświetlenia
NTAB:   DAT "     " ;tablica 5 spacji
        DAT 0       ;znak końca tekstu
NPTR:   DAT 0       ;adres poszczególnych cyfr
X:      DAT 0       ;zmienna pomocnicza

START:  LDA #NTAB    ;obliczamy adres 5 elementu + 1
        ADD #5
        STA NPTR     ;adres do zmiennej wskaźnikowej
LP1:    LDA N        ;obliczamy iloraz N przez 10
        DIV #10
        STA X        ;zapamiętujemy go chwilowo
        MUL #10      ;obliczamy resztę z dzielenia
        SUB N        ;reszta ujemna
        XOR #-1      ;obliczamy liczbę przeciwną w kodzie U2
        ADD #49      ;obliczamy kod ASCII cyfry
        STA (--NPTR) ;umieszczamy ją w tablicy
        LDA X        ;do N idzie wynik dzielenia przez 10
        STA N
        JZR #EX1     ;jeśli zero, to koniec przetwarzania
        JMP #LP1     ;w przeciwnym razie następna cyfra
EX1:    LDA #NTAB    ;wyświetlamy cyfry na wyświetlaczu
        STA NPTR
LP2:    LDA (NPTR++)
        JZR #0
        STA CHP
        INC CHI
        JMP #LP2

Wyświetlanie liczb dziesiętnych ze znakiem

Przedstawiony powyżej program potrafi wyświetlać poprawnie tylko liczby dodatnie i zero. Nie radzi sobie zupełnie z liczbami ujemnymi. Powodem jest sposób reprezentacji liczb ujemnych w pamięci maszyny - kod U2. Jednak prosta modyfikacja pozwoli wyświetlić również liczby ujemne.

Przed obliczaniem kolejnych cyfr sprawdzamy, czy liczba jest ujemna - jeśli tak, to zapamiętujemy ten fakt w osobnej zmiennej, np. wpisując tam znak "-". Następnie zamieniamy wartość liczby na przeciwną, obliczamy cyfry i na początku zapisu wpisujemy zapamiętany na początku znak "-". Ponieważ zapis liczby składa się teraz z maksymalnie 5 cyfr oraz znaku minus, to musimy powiększyć rozmiar tablicy przechowującej cyfry. Dla sprawdzenia, po wyliczeniu cyfr wyświetlamy je na wyświetlaczy znakowym.

        RUN START

N:      DAT -2457    ;liczba do wyświetlenia
NTAB:   DAT "      " ;tablica 6 spacji
        DAT 0        ;znak końca tekstu
NPTR:   DAT 0        ;adres poszczególnych cyfr
SGN:    DAT "+"      ;przechowuje informacje o znaku liczby
X:      DAT 0        ;zmienna pomocnicza

START:  LDA #NTAB    ;obliczamy adres 6 elementu + 1
        ADD #6
        STA NPTR     ;adres do zmiennej wskaźnikowej
        LDA N        ;sprawdzamy, czy N < 0
        JMI #MINUS
        JMP #LP1
MINUS:  XOR #-1      ;obliczamy wartość przeciwną
        ADD #1
        STA N
        LDA #"-"     ;do SGN wprowadzamy znak minus
        STA SGN
LP1:    LDA N        ;obliczamy iloraz N przez 10
        DIV #10
        STA X        ;zapamiętujemy go chwilowo
        MUL #10      ;obliczamy resztę z dzielenia
        SUB N        ;reszta ujemna
        XOR #-1      ;obliczamy liczbę przeciwną w kodzie U2
        ADD #49      ;obliczamy kod ASCII cyfry
        STA (--NPTR) ;umieszczamy ją w tablicy
        LDA X        ;do N idzie wynik dzielenia przez 10
        STA N
        JZR #EX1     ;jeśli zero, to koniec przetwarzania
        JMP #LP1     ;w przeciwnym razie następna cyfra
EX1:    LDA SGN      ;na początku dopisujemy znak liczby
        STA (--NPTR)
        LDA #NTAB    ;wyświetlamy cyfry na wyświetlaczu
        STA NPTR
LP2:    LDA (NPTR++)
        JZR #0
        STA CHP
        INC CHI
        JMP #LP2

Program wciąż nie radzi sobie z wartością -32768, która jest poprawna w kodzie U2. Spowodowane jest to tym, iż wartości tej nie można poprawnie zapisać jako liczby przeciwnej, dodatniej. Kod U2 jest kodem niesymetrycznym i dla 16 bitowych liczb ma zakres (-32768, 32767). Jedynym sensownym rozwiązaniem jest sprawdzenie tej wartości w programie i jeśli mamy z nią do czynienia, to w tablicy należy bezpośrednio umieścić odpowiednie cyfry i zakończyć obliczenia. Oto kompletny program wyświetlania dowolnych liczb w systemie PMC:

        RUN START

N:      DAT -2457    ;liczba do wyświetlenia
NTAB:   DAT "      " ;tablica 6 spacji
        DAT 0        ;znak końca tekstu
NPTR:   DAT 0        ;adres poszczególnych cyfr
SPCVAL: DAT -32768   ;wartość specjalna -32768
SPCASE: DAT "-32768" ;przechowuje bezpośredni zapis -32768
        DAT 0
SPTR:   DAT SPCASE   ;używane przy kopiowaniu tablic
SGN:    DAT "+"      ;przechowuje informacje o znaku liczby
X:      DAT 0        ;zmienna pomocnicza

START:  LDA N        ;sprawdzamy, czy N = -32768
        SUB SPCVAL
        JZR #SPEC
        JMP #NORMAL  ;jeśli nie, to idziemy normalnym torem
SPEC:   LDA #NTAB    ;skopiujemy tablicę znaków SPCASE
        STA NPTR     ;do NTAB
LP0:    LDA (SPTR++)
        STA (NPTR++)
        JZR #EX2
        JMP #LP0
NORMAL: LDA #NTAB    ;obliczamy adres 6 elementu + 1
        ADD #6
        STA NPTR     ;adres do zmiennej wskaźnikowej
        LDA N        ;sprawdzamy, czy N < 0
        JMI #MINUS
        JMP #LP1
MINUS:  XOR #-1      ;obliczamy wartość przeciwną
        ADD #1
        STA N
        LDA #"-"     ;do SGN wprowadzamy znak minus
        STA SGN
LP1:    LDA N        ;obliczamy iloraz N przez 10
        DIV #10
        STA X        ;zapamiętujemy go chwilowo
        MUL #10      ;obliczamy resztę z dzielenia
        SUB N        ;reszta ujemna
        XOR #-1      ;obliczamy liczbę przeciwną w kodzie U2
        ADD #49      ;obliczamy kod ASCII cyfry
        STA (--NPTR) ;umieszczamy ją w tablicy
        LDA X        ;do N idzie wynik dzielenia przez 10
        STA N
        JZR #EX1     ;jeśli zero, to koniec przetwarzania
        JMP #LP1     ;w przeciwnym razie następna cyfra
EX1:    LDA SGN      ;na początku dopisujemy znak liczby
        STA (--NPTR)
EX2:    LDA #NTAB    ;wyświetlamy cyfry na wyświetlaczu
        STA NPTR
LP2:    LDA (NPTR++)
        JZR #0
        STA CHP
        INC CHI
        JMP #LP2

Z podanych przykładów jasno wynika, iż procedury wyprowadzania liczb na wyświetlacze wcale nie są proste. Jest to prawdą również w świecie IBM. Zwróć uwagę, iż procedury wyświetlania liczb można bardzo prosto przystosować do innych systemów liczenia (np. piątkowego). Jednak przy wyświetlaniu liczb w systemie dwójkowym, ósemkowym i szesnastkowym korzysta się z innych metod, które uwzględniają sposób reprezentacji danych w pamięci maszyny, tj. bity.

Wyświetlanie liczb dwójkowych

Zapis dwójkowy zbudowany jest tylko z dwóch cyfr - 0 i 1. Teoretycznie moglibyśmy stosować odwrotny algorytm Hornera do obliczenia poszczególnych cyfr, tylko po co - przecież w komórce pamięci komputer przechowuje wartość w systemie dwójkowym. Wystarczy więc odczytać kolejne bity i wypisywać na wyświetlaczu cyfry 0 lub 1 w zależności od wartości tych bitów. Metody operacji bitowych omówiliśmy w poprzednim rozdziale. Poniżej przedstawiamy prosty program wyświetlający dowolną wartość w systemie dwójkowym. Wyświetlane jest zawsze 16 cyfr.

        RUN START

N:      DAT 23      ;tutaj umieszczamy liczbę do wyświetlenia
I:      DAT 0      ;zlicza bity

START:  LDA N       ;wydzielamy kolejne bity liczby
        RLA #1      ;obracając je w lewo
        STA N
        AND #1      ;gotowe
        ADD #48     ;tworzymy kod ASCII cyfry
        STA CHP     ;teraz na wyświetlacz
        INC CHI     ;następna pozycja
        INC I       ;zwiększamy licznik bitów
        LDA I
        SUB #16     ;koniec?
        JMI #START  ;następna cyfra, jeśli nie

Wyświetlanie liczb ósemkowych

Przy wyświetlaniu wartości ósemkowych skorzystamy z faktu, iż licząc od końca kolejne trzy bity wartości dwójkowej przedstawiają jedną cyfrę ósemkową w zakresie od 0 do 7. Jeśli przyjrzymy się komórce pamięci PMC, to stwierdzimy, iż pierwszą cyfrą ósemkową może być tylko cyfra 0 lub 1, a za nią następuje 5 cyfr już dowolnych:

Komórka pamięci PMC ósemkowo i dwójkowo
c5 c4 c3 c2 c1 c0
b15 b14 b13 b12 b11 b10 b09 b08 b07 b06 b05 b05 b03 b02 b01 b00

Poszczególne cyfry uzyskamy obracając bity w lewo i wykonując operację AND z maską 1 dla bitu b15 oraz 7 dla pozostałych bitów.

        RUN START

N:      DAT 864     ;tutaj podajemy wartość liczby
I:      DAT 0       ;licznik obiegów

START:  LDA N       ;najpierw bit 15
        RLA #1      ;bit b15 jest teraz na pozycji b0
        STA N
        AND #1      ;wydzielamy go
        JMP #DIGIT
LP1:    LDA N       ;wydzielamy po trzy bity
        RLA #3
        STA N
        AND #0B111  ;maska wydzielania bitów
DIGIT:  ADD #48     ;tworzymy kod cyfry
        STA CHP     ;przesyłamy go na wyświetlacz znakowy
        INC CHI     ;następna pozycja
        INC I       ;zwiększamy licznik obiegów
        LDA I       ;koniec?
        SUB #6      ;należy wykonać 6 obiegów pętli
        JMI #LP1

Wyświetlanie liczb szesnastkowych

Przy wyświetlaniu liczb szesnastkowych również wykorzystuje się fakt, iż licząc od końca każde kolejne 4 bity liczby dwójkowej przedstawiają jedną cyfrę szesnastkową. Problemem jest jedynie uzyskanie poprawnego kodu ASCII takiej cyfry. Nie wystarczy dodać do wartości cyfry kodu znaku "0" (48), ponieważ cyfry "A"..."F" będą źle przedstawione (literka A ma kod ASCII równy 65). My pójdziemy zupełnie inną drogą i po prostu umieścimy w pamięci tablicę ze wszystkimi cyframi szesnastkowymi. Otrzymana wartość cyfry będzie indeksem w tej tablicy, według którego pobierzemy odpowiedni znak.

        RUN START

N:      DAT 14978  ;tutaj umieszczamy liczbę do wyświetlenia
HEXTAB: DAT "0123456789ABCDEF"
HPTR:   DAT 0      ;do adresowania cyfr w tablicy
I:      DAT 0      ;licznik pętli

START:  LDA N        ;wydzielamy czwórki bitów obracając wartość
        RLA #4       ;o cztery pozycję w lewo i wykonując
        STA N        ;operację AND z maską 0B0000000000001111
        AND #15      ;w ACR wartość cyfry szesnastkowej
        ADD #HEXTAB  ;obliczamy adres znaku tej cyfry w tablicy
        STA HPTR
        LDA (HPTR++) ;pobieramy ten znak z tablicy
        STA CHP      ;i wyświetlamy go na wyświetlaczu znakowym
        INC CHI
        INC I        ;zwiększamy licznik obiegów pętli
        LDA I
        SUB #4       ;koniec?
        JMI #START   ;następna cyfra, jeśli nie

Na początek:  podrozdziału   strony 

Odczyt liczb

Liczby odczytujemy jako kolejne znaki cyfr. Znak cyfry ma kod ASCII (np. cyfra 0 to kod 48). Najpierw więc musimy przekształcać odczytane kody cyfr na ich wartość - polega to na odjęciu od kodu ASCII wartości 48 (kod cyfry 0). Następnie stosujemy algorytm Hornera do obliczenia wartości liczby.

Brzmi to dosyć prosto. Jednak musisz rozważyć kilka ważnych spraw przy opracowaniu poprawnego programu odczytu liczby. Przede wszystkim program będzie współpracował z użytkownikiem, który jest istotą nieprzewidywalną i omylną. Dobrze skonstruowany algorytm powinien działać poprawnie w każdej sytuacji, nawet jeśli użytkownik wprowadzi bezsensowny stek bzdur (są tacy, nawet wśród was, którzy lubią w ten sposób męczyć komputery). Z drugiej strony użytkownik może wprowadzić liczbę za dużą lub za małą, to też musi sprawdzać program Widzisz więc, iż odczyt liczb komplikuje się znacznie, gdy chcemy się zabezpieczyć przed możliwymi błędami ze strony człowieka.

Odczyt liczb dziesiętnych bez znaku

obrazek

Poniższa wersja programu nie sprawdza poprawności wprowadzonych danych, dlatego nie jest odporna na błędy użytkownika. Najpierw program czeka, aż w buforze pojawią się dane, które musi wprowadzić użytkownik. Gdy dane są dostępne, to program odczytuje je znak po znaku. Zakładamy, iż są to kolejne cyfry liczby. Każdy znak cyfry jest sprowadzany do wartości cyfry przez zmniejszenie kodu o 48. Wartości te są dodawane do wyniku przemnożonego przez 10 (schemat Hornera). Pętla jest kończona, gdy w buforze wyczerpią się znaki. Program działa poprawnie dla liczb z zakresu od 0 do 65535. Ponieważ jednak PMC pracuje w kodzie U2, to liczby większe od 32767 będą przedstawiane jako ujemne (najstarszy bit ma wartość 1).

Program można rozbudować według następujących wskazówek:

  1. Zabezpieczenie przed przekroczeniem zakresu liczb dodatnich w kodzie U2. Jeśli w trakcie obliczeń wartości N otrzymamy liczbę ujemną, to znaczy, iż przekroczono zakres. Więc każdorazowo po wykonaniu operacji N · 10 + znak - 48 należy sprawdzić znak wyniku i przerwać obliczanie w przypadku błędu.
  2. Zabezpieczenie przed błędnymi znakami. Po odczytani znaku należy sprawdzić, czy jego kod wpada w zakres poprawnych kodów ASCII dla cyfr (48...57). Jeśli jest poza tym zakresem, to użytkownik wprowadził zły znak i obliczenia należy przerwać.
  3. Po przerwaniu obliczeń bufor wejściowy INP powinien zostać oczyszczony ze znaków (znaki odczytujemy, aż otrzymamy kod -1). Następnie program powinien spróbować ponownie odczytać liczbę. Być może jakaś informacja dla użytkownika byłaby bardzo pożądana.

Rozbudowę pozostawiamy ambitnym czytelnikom.

        RUN START

N:      DAT 0  ;tutaj trafi odczytana liczba
X:      DAT 0  ;zmienna pomocnicza

START:  LDA INP    ;odczytujemy znak z bufora
        JZR #START ;bufor zajęty?
        JMI #START ;bufor pusty?
LP1:    SUB #"0"   ;obliczamy wartość cyfry
        STA X      ;i zapamiętujemy ją tymczasowo
        LDA N      ;N przemnażamy przez 10
        MUL #10
        ADD X      ;dodajemy cyfrę
        STA N      ;zapisujemy wynik
LP2:    LDA INP    ;pobieramy kolejny znak
        JZR #LP2   ;czekamy na dostępność bufora
        JMI #0     ;ale kończymy, gdy pusty. Wynik w N
        JMP #LP1   ;inaczej przetwarzamy znak

Odczyt liczb dziesiętnych ze znakiem

Odczyt liczb ze znakiem nie różni się zasadniczo od odczytu liczb bez znaku. Jedyną nowością jest dodatkowy znak, który może pojawić się na początku zapisu, mianowicie minus. Program odczytujący powinien sprawdzić, czy pierwszy znak jest minusem. Jeśli tak, to zostaje ustawiony odpowiedni znacznik. Teraz następuje odczyt liczby bez znaku. Po odczytaniu liczby program sprawdza znacznik i jeśli jest on ustawiony, zmienia wartość liczby na przeciwną.

        RUN START

N:      DAT 0  ;tutaj trafi odczytana liczba
SGN:    DAT 0  ;znacznik liczby ujemnej
X:      DAT 0  ;zmienna pomocnicza

START:  LDA INP    ;odczytujemy znak z bufora
        JZR #START ;bufor zajęty?
        JMI #START ;bufor pusty?
        STA X      ;zapamiętujemy chwilowo znak
        SUB #"-"   ;sprawdzamy, czy odczytano minus
        JZR #MINUS
        LDA X      ;jeśli nie, to odtwarzamy znak
        JMP #LP1   ;i przetwarzamy go
MINUS:  INC SGN    ;ustawiamy znacznik
        JMP #LP2   ;i przechodzimy do odczytu cyfr
LP1:    SUB #"0"   ;obliczamy wartość cyfry
        STA X      ;i zapamiętujemy ją tymczasowo
        LDA N      ;N przemnażamy przez 10
        MUL #10
        ADD X      ;dodajemy cyfrę
        STA N      ;zapisujemy wynik
LP2:    LDA INP    ;pobieramy kolejny znak
        JZR #LP2   ;czekamy na dostępność bufora
        JMI #EX1   ;ale kończymy, gdy pusty
        JMP #LP1   ;inaczej przetwarzamy znak
EX1:    LDA SGN    ;liczba ujemna?
        JZR #0     ;kończymy, jeśli nie. Wynik w N.
        LDA #0     ;inaczej zmieniamy znak N
        SUB N
        STA N

Odczyt liczb dwójkowych i ósemkowych

Program odczytujący liczbę dwójkową można skonstruować na bazie poprzednio przedstawionego programu dla liczb dziesiętnych. Jednak chciałbym pokazać wam nieco inne podejście do tego problemu. Ponieważ liczby są przechowywane w pamięci komputera w postaci bitów, to możemy bezpośrednio odczytywać cyfry dwójkowe, zamieniać je na bity o wartości 0 lub 1 i wstawiać do tworzonej liczby, która przed tą operacją jest przesuwana bitowo o jedną pozycję w lewo.

        RUN START

N:      DAT 0  ;tutaj trafi odczytana liczba dwójkowa
X:      DAT 0  ;zmienna pomocnicza

START:  LDA INP    ;odczytujemy znak z bufora
        JZR #START ;bufor zajęty?
        JMI #START ;bufor pusty?
LP1:    SUB #"0"   ;obliczamy wartość cyfry 0 lub 1
        STA X      ;i zapamiętujemy ją tymczasowo
        LDA N      ;N przesuwamy o 1 pozycję w lewo
        RLA #1
        ORA X      ;wstawiamy bit
        STA N      ;zapisujemy wynik
LP2:    LDA INP    ;pobieramy kolejny znak
        JZR #LP2   ;czekamy na dostępność bufora
        JMI #0     ;ale kończymy, gdy pusty. Wynik w N
        JMP #LP1   ;inaczej przetwarzamy znak

Dla liczb ósemkowych modyfikacja algorytmu jest minimalna. Wystarczy przesuwać bitowo zmienną N o trzy pozycję w lewo - cyfra ósemkowa zastępuje trzy bity liczby dwójkowej.

        RUN START

N:      DAT 0  ;tutaj trafi odczytana liczba ósemkowa
X:      DAT 0  ;zmienna pomocnicza

START:  LDA INP    ;odczytujemy znak z bufora
        JZR #START ;bufor zajęty?
        JMI #START ;bufor pusty?
LP1:    SUB #"0"   ;obliczamy wartość cyfry od 0 do 7
        STA X      ;i zapamiętujemy ją tymczasowo
        LDA N      ;N przesuwamy o 3 pozycję w lewo
        RLA #3
        ORA X      ;wstawiamy bity cyfry ósemkowej
        STA N      ;zapisujemy wynik
LP2:    LDA INP    ;pobieramy kolejny znak
        JZR #LP2   ;czekamy na dostępność bufora
        JMI #0     ;ale kończymy, gdy pusty. Wynik w N
        JMP #LP1   ;inaczej przetwarzamy znak

Odczyt liczb szesnastkowych

Sam algorytm obliczania wartości liczby szesnastkowej nie różni się niczym od opisanych powyżej algorytmów dla liczb dwójkowych i ósemkowych - jedna cyfra szesnastkowa zajmuje cztery bity, więc liczbę przesuwamy w lewo bitowo o cztery pozycje i łączymy bity cyfry szesnastkowej z liczbą. Problemem jednak będzie obliczenie wartości cyfry szesnastkowej. Z bufora wejściowego INP cyfry odczytujemy jako znaki w kodzie ASCII. Dla cyfr "0" ... "9" nie ma problemu. Wystarczy od kodu znaku odjąć wartość 48, aby otrzymać wartość tej cyfry. Jednak cyfry literowe "A" ... "F" mogą początkującemu programiście sprawić nieco kłopotu. Ich kody leżą dalej w zestawie ASCII od kodów cyfr "0" ... "9". Co gorsza, użytkownik może wprowadzić zamiast dużych liter małe znaki "a" ... "f". W poniższej tabelce zebraliśmy kody ASCII wszystkich cyferek szesnastkowych.

cyfry normalne cyfry literowe
0
48
1
49
2
50
3
51
4
52
5
53
6
54
7
55
8
56
9
57
A
65
B
66
C
67
D
68
E
69
F
70
  a
97
b
98
c
99
d
100
e
101
f
102

Aby otrzymać poprawną wartość cyfry musimy wykonać następujące obliczenia:

cyfra ← cyfra - 48
jeśli cyfra > 9, to cyfra ← cyfra - 7
jeśli cyfra > 15, to cyfra ← cyfra - 32

Sprawdźmy: użytkownik podał cyfrę "d" o kodzie 100

cyfra = 100 - 48 = 52
52 > 9, więc cyfra = 52 - 7 = 45
45 > 15, więc cyfra = 45 - 32 = 13, co jest wartością cyfry D.

Po tych wyjaśnieniach możemy przejść do programu odczytującego liczby w kodzie szesnastkowym.

        RUN START

N:      DAT 0  ;tutaj trafi odczytana liczba szesnastkowa
X:      DAT 0  ;zmienna pomocnicza

START:  LDA INP    ;odczytujemy znak z bufora
        JZR #START ;bufor zajęty?
        JMI #START ;bufor pusty?
LP1:    SUB #48    ;cyfra <- cyfra - 48
        STA X      ;i zapamiętujemy ją tymczasowo
        SUB #10    ;cyfra < 9 ?
        JMI #CYFRA
        ADD #3     ;cyfra <- cyfra - 7
        STA X
        SUB #16    ;cyfra < 15 ?
        JMI #CYFRA
        SUB #16    ;cyfra <- cyfra - 32
        STA X
CYFRA:  LDA N      ;N przesuwamy o 4 pozycję w lewo
        RLA #4
        ORA X      ;wstawiamy bity cyfry ósemkowej
        STA N      ;zapisujemy wynik
LP2:    LDA INP    ;pobieramy kolejny znak
        JZR #LP2   ;czekamy na dostępność bufora
        JMI #0     ;ale kończymy, gdy pusty. Wynik w N
        JMP #LP1   ;inaczej przetwarzamy znak

Na początek:  podrozdziału   strony 

Odczyt stanu przycisków IOP

Odczytując port IOP dostajemy stan przycisków panelu IOP. Każdy przycisk ma skojarzony ze sobą jeden bit portu. Odczyt będzie więc polegał na sprawdzeniu stanu odpowiedniego bitu. Poniższy program zaprzestaje działania, po kliknięciu przycisku nr 3.

        RUN START

START:  LDA IOP    ;odczytujemy stan przycisków
        AND #8     ;sprawdzamy stan bitu nr 3
        JZR #START ;jeśli nie jest naciśnięty, to kontynuujemy

A ten prosty program odczytuje stan przycisków IOP i mruga diodami LED nad wciśniętymi przyciskami:

        RUN START

MASKA:   DAT 0

START:  LDA IOP   ;odczytujemy stan przycisków
        AND MASKA ;bity ustawiamy lub zerujemy
        STA IOP   ;zaświecamy diody
        LDA MASKA ;negujemy bity maski
        XOR #-1
        STA MASKA
        LDA #-5   ;małe opóźnienie
LP1:    ADD #1
        JMI #LP1
        JMP #START

W następnym programie odczytywany jest stan trzech przycisków. W zależności od ich stanu program obraca na wyświetlaczu znakowym literkę A w lewo, gdy naciśnięty jest przycisk 1; w prawo, gdy naciśnięty jest przycisk 0 oraz kończy działanie, gdy naciśnięty jest przycisk 2.

        RUN START

START:  LDA #"A"    ;umieszczamy znak A na wyświetlaczu
        STA CHP
LP1:    LDA IOP     ;sprawdzamy stan przycisku 0
        AND #1
        JZR #N1     ;jeśli wyciśnięty, to dalej
        LDA #261    ;wciśnięty, obrót znaków w prawo
        STA CHP
N1:     LDA IOP     ;sprawdzamy stan przycisku 1
        AND #2
        JZR #N2     ;jeśli wyciśnięty, to dalej
        LDA #260    ;wciśnięty, obrót znaków w lewo
        STA CHP
N2:     LDA IOP     ;sprawdzamy stan przycisku 2
        AND #4
        JZR #LP1    ;jeśli wyciśnięty, to kontynuujemy pętlę

Kolejny program demonstruje sposób odczytu sekwencji przycisków. Program kończy wykonanie, gdy naciśnięte są jednocześnie trzy przyciski 0, 2 i 5.

        RUN START

START:  LDA IOP       ;odczytujemy stan wszystkich przycisków
        AND #0B100101 ;wydzielamy bity 5,2 i 0
        XOR #0B100101 ;sprawdzamy, czy są ustawione na 1
        JZR #EX1      ;jeśli tak, to kończymy
        JMP #START
EX1:

Na początek:  podrozdziału   strony 

Sterowanie wyświetlaczami 7-segmentowymi LED

obrazek

Sterowanie wyświetlaczami 7-mio segmentowymi LED odbywa się podobnie do sterowania portem znakowym. Mamy tutaj port indeksowy DSI, do którego wprowadzamy numer aktywnego wyświetlacza. Port ten jest 4 bitowy. Pierwszy wyświetlacz znajduje się po prawej stronie i ma numer 0. Po wprowadzeniu numeru do DSI komputer uzyskuje dostęp do poszczególnych segmentów LED wybranego wyświetlacza poprzez port DSP. Odczyt tego portu zwraca informację, które z segmentów są zaświecone (skojarzone z nimi bity mają stan 1). Zapis do tego portu powoduje zaświecenie odpowiednich segmentów.

Świeceniem segmentów sterują bity od b0 do b6. Bit b7 steruje świeceniem kropki przy cyfrze. Port DSP jest 8-mio bitowy.

Taki sposób sterowania, chociaż nie pozwala bezpośrednio wyświetlać cyfr (wpisanie wartości cyfry do portu DSP nie spowoduje pojawienia się jej na wyświetlaczu), to jednak daje pełną kontrolę nad świeceniem poszczególnych segmentów. Dzięki temu można również tak wysterować segmenty wyświetlacza, aby pojawiły się na nich niektóre literki lub znaki.

Prezentowany poniżej program zaświeca wszystkie segmenty we wszystkich wyświetlaczach.

        RUN START

START:  LDA #0B11111111 ;ustawione wszystkie 8 bitów
        STA DSP         ;zapalamy wszystkie segmenty
        INC DSI         ;przechodzimy do następnego wyświetlacza
        LDA DSI         ;koniec?
        JZR #0          ;kończymy, jeśli tak
        JMP #START      ;następny wyświetlacz, jeśli nie

Poeksperymentuj w tym programie z wartością wprowadzaną na jego początku do rejestru akumulatora. Np. wpisz taką wartość, aby na wszystkich wyświetlaczach pojawiły się cyfry 0, 1, 2, itd.

Kolejny program demonstruje sposób wyświetlania cyfr. Dane dla wyświetlacza LED zgromadzone zostały w tablicy w ten sposób, iż element o indeksie np. 3 zawiera kształt cyfry 3 dla portu DSP. Program zamienia więc wartość cyfry na element z tablicy DSPTAB o indeksie równym tej cyfrze, następnie przesyła ten element do portu DSP. W rezultacie na wyświetlaczu otrzymujemy kształty kolejnych cyfr.

        RUN START

N:      DAT 0            ;licznik
DSPTAB: DAT 0B0111111    ;cyfra 0
        DAT 0B0000011    ;cyfra 1
        DAT 0B1101101    ;cyfra 2
        DAT 0B1100111    ;cyfra 3
        DAT 0B1010011    ;cyfra 4
        DAT 0B1110110    ;cyfra 5
        DAT 0B1111110    ;cyfra 6
        DAT 0B0100011    ;cyfra 7
        DAT 0B1111111    ;cyfra 8
        DAT 0B1110111    ;cyfra 9
DTPTR:  DAT 0            ;do adresowania tablicy

START:  LDA N         ;N zamieniamy na kod dla portu wyświetlacza
        ADD #DSPTAB   ;obliczamy adres elementu
        STA DTPTR
        LDA (DTPTR++) ;pobieramy kod dla wyświetlacza
        STA DSP       ;zapalamy odpowiednie segmenty LED
        LDA #-25      ;pętla opóźniająca
LP1:    ADD #1
        JMI #LP1  
        INC N         ;zwiększamy N o 1
        LDA N         ;sprawdzamy, czy  N > 9
        SUB #10
        JMI #START
        LDA #0        ;jeśli tak, to zerujemy licznik
        STA N
        JMP #START        

A tutaj mamy przykład licznika liczącego w kodzie szesnastkowym. W tablicy zdefiniowano dodatkowe cyfry A...F.

        RUN START

N:      DAT 0            ;licznik
DSPTAB: DAT 0B0111111    ;cyfra 0
        DAT 0B0000011    ;cyfra 1
        DAT 0B1101101    ;cyfra 2
        DAT 0B1100111    ;cyfra 3
        DAT 0B1010011    ;cyfra 4
        DAT 0B1110110    ;cyfra 5
        DAT 0B1111110    ;cyfra 6
        DAT 0B0100011    ;cyfra 7
        DAT 0B1111111    ;cyfra 8
        DAT 0B1110111    ;cyfra 9
        DAT 0B1111011    ;cyfra A
        DAT 0B1011110    ;cyfra b
        DAT 0B0111100    ;cyfra C
        DAT 0B1001111    ;cyfra d
        DAT 0B1111100    ;cyfra E
        DAT 0B1111000    ;cyfra F
DTPTR:  DAT 0            ;do adresowania tablicy

START:  LDA N         ;N zamieniamy na kod dla portu wyświetlacza
        AND #0B1111   ;pozostawiamy tylko cztery najmłodsze bity
        ADD #DSPTAB   ;obliczamy adres elementu
        STA DTPTR
        LDA (DTPTR++) ;pobieramy kod dla wyświetlacza
        STA DSP       ;zapalamy odpowiednie segmenty LED
        LDA #-25      ;pętla opóźniająca
LP1:    ADD #1
        JMI #LP1  
        INC N         ;zwiększamy N o 1
        JMP #START        

Kolejny program jest modyfikacją programu wyświetlania liczb dziesiętnych bez znaku. Tym razem liczba zostaje umieszczona na wyświetlaczach 7-mio segmentowych LED. Wyświetlacze są sterowane bezpośrednio bez umieszczania cyfr w pamięci. Program łatwo można dostosować do innych systemów pozycyjnych przez zmianę wartości stałej P.

        RUN START

P:      EQU 10      ;określa podstawę systemu 2..16
N:      DAT 31857   ;liczba do wyświetlenia
X:      DAT 0       ;zmienna pomocnicza
DSPTAB: DAT 0B0111111    ;cyfra 0
        DAT 0B0000011    ;cyfra 1
        DAT 0B1101101    ;cyfra 2
        DAT 0B1100111    ;cyfra 3
        DAT 0B1010011    ;cyfra 4
        DAT 0B1110110    ;cyfra 5
        DAT 0B1111110    ;cyfra 6
        DAT 0B0100011    ;cyfra 7
        DAT 0B1111111    ;cyfra 8
        DAT 0B1110111    ;cyfra 9
        DAT 0B1111011    ;cyfra A
        DAT 0B1011110    ;cyfra b
        DAT 0B0111100    ;cyfra C
        DAT 0B1001111    ;cyfra d
        DAT 0B1111100    ;cyfra E
        DAT 0B1111000    ;cyfra F
DTPTR:  DAT 0            ;do adresowania tablicy

START:  LDA #0        ;ustawiamy wyświetlacz na ostatnią cyfrę
        STA DSI
LP1:    LDA N         ;obliczamy iloraz N przez P
        DIV #P
        STA X         ;zapamiętujemy go chwilowo
        MUL #P        ;obliczamy resztę z dzielenia
        SUB N         ;reszta ujemna
        XOR #-1       ;obliczamy liczbę przeciwną w kodzie U2
        ADD #1
        ADD #DSPTAB   ;obliczamy adres kształtu cyfry
        STA DTPTR
        LDA (DTPTR++) ;pobieramy definicję cyfry
        STA DSP       ;wyświetlamy ją
        INC DSI       ;ustawiamy kolejną pozycję
        LDA X         ;do N idzie wynik dzielenia przez 10
        STA N
        JZR #0        ;jeśli zero, to koniec przetwarzania
        JMP #LP1      ;w przeciwnym razie następna cyfra

Oprócz wyświetlania liczb wyświetlacze 7-mio segmentowe LED mogą również służyć do prostych animacji. Poniższy program wyświetla na ostatnim wyświetlaczu biegającą w kółko kreseczkę.

        RUN START
MASK:   DAT 1

START:  LDA #-10    ;małe opóźnienie
LP1:    ADD #1
        JMI #LP1
        LDA MASK    ;odczytujemy maskę
        STA DSP     ;zapalamy segment
        RLA #1      ;maskę przesuwamy o 1 bit w lewo
        STA MASK
        AND #0B1000000
        JZR #START  ;jeśli bit 7 zero, to powtarzamy
        LDA #1      ;inaczej ustawiamy maskę od nowa
        STA MASK
        JMP #START

Ten program z kolei wyświetla kreseczkę przebiegającą przez kolejne wyświetlacze.

        RUN START

START:  LDA #0B1000000
        STA DSP   ;zapalamy kreseczkę (segment g)
        LDA #-10  ;małe opóźnienie
LP1:    ADD #1
        JMI #LP1
        STA DSP   ;gasimy kreseczkę
        INC DSI   ;przenosimy się do następnej pozycji
        JMP #START

Sprawdźcie osobiście, co robi poniższy program:

        RUN START

START:  LDA #0B1001110
        XOR DSP
        STA DSP
        INC DSI
        JMP #START

Na początek:  podrozdziału   strony 

Operacje graficzne

PMC wyposażona jest w prosty ekranik graficzny, którym sterujemy za pomocą dwóch portów: GRP i GRI. W pierwszym porcie ustawiamy lub odczytujemy kolor punktu. W drugim porcie ustawiamy lub odczytujemy położenie punktu na ekranie. Współrzędne x i y mają zakres od 0 do 15.

Stawianie punktu na zadanych współrzędnych

Umieszczenie punktu na ekranie graficznym składać się będzie z następujących operacji:

  1. Połączenie współrzędnych x (0...15) i y (0...15) w jedno słowo i zapis tego słowa do portu GRI. W ten sposób uzyskujemy dostęp do punktu ekranu graficznego leżącego na współrzędnych (x,y).
  2. Połączenie składowych koloru w jedno słowo zawierające kod koloru RGB i zapis tego słowa do portu GRP. W ten sposób sprawimy, iż wcześniej wybrany punkt na współrzędnych (x,y) otrzyma zadaną barwę

Poniższy program realizuje wymienione operacje. Umieszcza on punkt o kolorze określonym przez zmienne R (składowa czerwona), G (składowa zielona) oraz B (składowa niebieska) na współrzędnych określonych przez zmienne X oraz Y.

        RUN START

R:      DAT 15   ;czterobitowa składowa czerwona koloru
G:      DAT  0   ;czterobitowa składowa zielona koloru
B:      DAT  0   ;czterobitowa składowa niebieska koloru
X:      DAT  7   ;współrzędna x
Y:      DAT  7   ;współrzędna y

START:  LDA Y    ;łączymy współrzędne x i y w jedno słowo
        RLA #4
        ORA X
        STA GRI  ;ustawiamy pozycję punktu
        LDA R    ;łączymy składowe kolorów
        RLA #4
        ORA G
        RLA #4
        ORA B
        STA GRP  ;ustawiamy kolor punktu

Odczytywanie koloru punktu na zadanych współrzędnych

W niektórych algorytmach graficznych (np. wypełniania obszaru kolorem) istotne jest odczytanie koloru punktu leżącego na zadanych współrzędnych. Polega to na wykonaniu następujących operacji:

  1. Połączenie współrzędnych x (0...15) i y (0...15) w jedno słowo i zapis tego słowa do portu GRI. W ten sposób uzyskujemy dostęp do punktu ekranu graficznego leżącego na współrzędnych (x,y).
  2. Odczyt koloru punktu z portu GRP.
  3. Rozłożenie odczytanego koloru na poszczególne składowe R, G i B.

Poniższy program odczytuje składowe koloru punktu na zadanych współrzędnych i wpisuje je do zmiennych R (składowa czerwona), G (składowa zielona) i B (składowa niebieska). Przed odczytem ekranik graficzny jest wypełniany zadanym kolorem w celu przetestowania działania procedury.

        RUN START

KOL:     DAT 0xFF0    ;kolor żółty do testowego wypełnienia
R:       DAT 0        ;tutaj trafi składowa czerwona
G:       DAT 0        ;tutaj trafi składowa zielona
B:       DAT 0        ;tutaj trafi składowa niebieska
X:       DAT 5        ;współrzędna X odczytywanego punktu
Y:       DAT 2        ;współrzędna Y odczytywanego punktu

START:   LDA KOL      ;wypełniamy ekranik graficzny kolorem
         STA GRP
         INC GRI      ;następny punkt
         LDA GRI
         JZR #D1
         JMP #START
D1:      LDA Y        ;łączymy współrzędne
         RLA #4
         ORA X
         STA GRI      ;udostępniamy punkt (x,y)
         LDA GRP      ;pobieramy kolor
         STA R        ;chwilowo zapamiętujemy go w R
         AND #0B1111  ;wydzielamy bity koloru niebieskiego
         STA B
         LDA R        ;odtwarzamy kolor
         RLA #-4      ;przesuwamy bity koloru zielonego na pozycję
         AND #0B1111  ;wydzielamy je
         STA G
         LDA R        ;i to samo z bitami koloru czerwonego
         RLA #-8
         AND #0B1111
         STA R

Proste efekty graficzne

Efekty graficzne można uzyskiwać bardzo prostymi środkami. Poniższy program wypełnia ekranik graficzny punktami o coraz wyższych kolorach.

        RUN START

START:  INC GRP  ;zwiększamy kolor punktu na danych współrzędnych
        INC GRI  ;przechodzimy do następnego punktu
        JMP #START

Jeszcze ciekawszy efekt da nam poniższy program:

        RUN START

START:  LDA #0    ;rozpoczynamy od koloru czarnego
LP1:    STA GRP   ;ustawiamy kolor punktu
        INC GRI   ;przechodzimy do następnego punktu
        ADD #1    ;zwiększamy kolor w akumulatorze
        JMP #LP1  ;kontynuujemy pętlę

Następny program tworzy na ekranie graficznym efekt szachownicy. Kolory punktów jasnych i ciemnych są przechowywane w zmiennych KOL1 i KOL2.

        RUN START

KOL1:   DAT 0xFF0   ;żółty kolor
KOL2:   DAT 0x00F   ;niebieski kolor
MASK:   DAT 0

START:  LDA MASK    ;jaki punkt postawić?
        JZR #D1     ;0 - KOL2
        LDA KOL1    ;1 - KOL1
        JMP #D2
D1:     LDA KOL2
D2:     STA GRP     ;ustawiamy kolor punktu
        LDA MASK    ;zmieniamy bit 0 maski na przeciwny
        XOR #1
        STA MASK
        INC GRI     ;przesuwamy się do następnej pozycji
        LDA GRI     ;sprawdzamy, czy koniec
        JZR #0      ;kończymy, jeśli tak
        AND #0xF    ;sprawdzamy, czy wypełniliśmy 1 wiersz
        JZR #D3
        JMP #START  ;jeśli nie, to kontynuujemy
D3:     LDA MASK    ;jeśli tak, to w następnym wierszu musimy
        XOR #1      ;odwrócić układ kolorów, aby powstawała
        STA MASK    ;szachownica
        JMP #START

Kolejny z programów wnosi nieco animacji na ekranik graficzny. PMC nie pracuje zbyt szybko, więc efekty animacyjne nie będą zaawansowane. Program symuluje odbijającą się piłeczkę. Piłeczka jest punktem, który zmienia współrzędne. Gdy osiągnie jedną z krawędzi ekranu następuje zmiana kierunku ruchu w osi, w której wystąpiła ta krawędź.

        RUN START

KOL:    DAT 0xF0F      ;kolor piłeczki
X:      DAT 5          ;współrzędna x
Y:      DAT 2          ;współrzędna y
OX:     DAT 0          ;stara współrzędna x
OY:     DAT 0          ;stara współrzędna y
DX:     DAT 1          ;przyrost w osi x
DY:     DAT 1          ;przyrost w osi y

START:  LDA Y      ;łączymy współrzędne i wpisujemy
        RLA #4     ;wynik do portu indeksowego grafiki  
        ORA X
        STA GRI
        LDA KOL    ;ustawiamy kolor punktu (piłeczka)
        STA GRP
        LDA X      ;zapamiętujemy bieżące współrzędne
        STA OX
        ADD DX     ;przesuwamy piłeczkę w osi x
        STA X
        JZR #MDX   ;sprawdzamy, czy piłeczka osiągnęła ścianę
        XOR #15    ;w osi x
        JZR #MDX
        JMP #ON1   ;jeśli nie, to przechodzimy do współrzędnej y
MDX:    SUB DX     ;jeśli tak, to zmieniamy kierunek ruchu
        STA DX     ;w osi x (przeciwny przyrost)
ON1:    LDA Y      ;ze współrzędną y wykonujemy identyczne
        STA OY     ;operacje
        ADD DY
        STA Y
        JZR #MDY
        XOR #15
        JZR #MDY
        JMP #ON2
MDY:    SUB DY
        STA DY
ON2:    LDA OY     ;łączymy stare współrzędne i zapisujemy
        RLA #4     ;do portu indeksowego grafiki
        ORA OX
        STA GRI
        LDA #0     ;następnie wymazujemy punkt (piłeczkę)
        STA GRP
        JMP #START ;i kontynuujemy pętlę

Na początek:  podrozdziału   strony 

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2024 mgr Jerzy Wałaszek

Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.

Informacje dodatkowe.