Tajemnice ATARI

PROGRAMOWANIE PROCESORA 6502
W KOMPUTERACH ATARI XL/XE - cz.II

Krótkie przypomnienie

Dotychczas nabyte wiadomości powinny wystarczyć do napisania takiego programu:
        OPT   21 opcje
        ORG 1152 skąd

*--- deklaracje
 ZEGAR  EQU  20
 RAMKA  EQU 712
 KLAW   EQU 764
 NIC    EQU 255

*--- zapamiętaj kolor
        LDX RAMKA

*--- mrugaj ramką
MRUGAJ  LDA ZEGAR
        STA RAMKA
*--- sprawdź klawisz
        LDY KLAW
        INY (255+1=0)
        BEQ MRUGAJ
*--- skasuj klawisz
        LDY #NIC
        STY KLAW
*--- odtwórz kolor
        STX RAMKA
*--- koniec
        RTS
        END

Odrobina nudnej, ale
koniecznej teorii
na temat liczb

System dziesiętny, stosowany z upodobaniem przez ludzi, z racji budowy ich kończyn, charakteryzuje się tym (i stad bierze swą nazwę), że liczba różnych cyfr, (a więc i liczb możliwych do przedstawienia jedną cyfrą) jest równa 10. Chcę tu zwrócić uwagę, że liczba jest pojęciem abstrakcyjnym, istotnie różnym od jej zapisu na papierze, będącym tylko jej interpretacją wizualną w postaci ciągu znaków, zwanych cyframi. Dobór tych znaków zależy od umowy i może być (a nawet bywa) różny, choć opisuje tę samą liczbę. Dlatego nie będziemy mówić o liczbach dziesiętnych i dwójkowych, lecz o zapisie dwójkowym, dziesiętnym, itd. Istota liczby nie zmienia się bowiem w zależności od sposobu jej przedstawienia.

We wnętrzu komputera liczby są zapisywane w obwodach elektrycznych za pomocą napięć o ustalonych, łatwych do porównania, poziomach. Pojedynczym elementem liczby w komputerze jest przerzutnik, czyli obwód mogący trwać w jednym z dwóch stanów: "włączony" i "wyłączony". Odpowiednikiem graficznym takiego elementu jest pojedynczy znak (cyfra) z dwuznakowego repertuaru, np. "H" i "L" albo "-" i "+", itd. Łatwo spostrzec, że jeden taki element pamięciowy, zwany bitem, jest w stanie "udźwignąć" niewiele różnych liczb (dokładnie dwie). Jeśli jednak potraktować kilka bitów wspólnie jako zapis jednej liczby, możliwości te szybko rosną. Grupa ośmiu bitów może przyjąć 256 różnych stanów. Taką grupę przyjęto nazywać bajtem.

W języku asemblera możemy przedstawiać liczby zarówno dziesiętnie, zgodnie z powszednią praktyką, jak i dwójkowo (bitowo). Do zapisu dwójkowego stosujemy cyfry "0" i "1", co dobrze wspomaga intuicję, a cały ciąg cyfr poprzedzamy znakiem "%". Taki zapis stosuje się szczególnie wtedy, gdy trzeba odwołać się do poszczególnych bitów jakiegoś bajtu, np. w celu włączenia silnika magnetofonu, co jest związane z trzecim bitem bajtu 54018.
        LDA #%00110100
        STA 54018 start
włącza silnik, zaś
        LDA #%00111100
        STA 54018 stop
wyłącza go. Pamiętajmy, że bity są numerowane od prawej strony, a skrajny ma numer 0.

Z uwagi na zakres wartości będziemy dzielić liczby na "krótkie" i "długie". Krótkimi nazywamy te z liczb, które dają się zapisać przy pomocy jednego bąjtu, a więc od 0 do 255. W potocznej formie będziemy też na nie mówić po prostu "bajt". Liczby długie przyjmują wartości z zakresu od O do 65535, a dla ich wyrażenia komputer potrzebuje dwóch bajtów. Takie liczby nazywamy nieraz "adresami". Jako że ich zakres odpowiada przestrzeni adresowej naszego komputera. Dwubajtowy fragment pamięci potrzebny dla pomieszczenia adresu zwie się "słowem". Potocznie nie akcentuje się różnic znaczenia zwrotów "słowo", "adres", "liczba długa", nierzadko będziemy ich używać zamiennie. Zawsze jednak, gdy będzie mowa o słowie, np. pod adresem 560 pamiętajmy, że zajmuje ono dwa kolejne bajty: 560 i 561.

Operacje logiczne

Manipulacja silnikiem magnetofonu pokazaną wyżej metodą zakłada, że pozostałe bity mają takie właśnie wartości, jak w przykładzie. Jeśli jest inaczej, oprócz włączenia silnika może to spowodować niepożądane skutki uboczne. Aby tak się nie stało, trzeba "poruszyć" tylko ten jeden, wybrany bit. Rozkazy AND, ORA i EOR działają na odpowiednie bity akumulatora i argumentu w pamięci według: znanych ze szkoły "tabelek prawdy":

bit w
A
bit w
pamięci
wynik
AND
wynik
ORA
wynik
EOR
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 1 0

Wynik operacji pozostaje w akumulatorze. A zatem
STER_A EQU 54018
BIT_3  EQU %00001000
BIT_3_ EQU %11110111

       LDA STER_A
       AND #BIT_3_ 
       STA STER_A
wyzeruje trzeci bit rejestru sterującego portu A, czyli włączy silnik magnetofonu, natomiast
       LDA STER_A
       ORA #BIT_3
       STA STER_A
wyłączy magnetofon, nie ruszając pozostałych bitów. Taki układ zer i jedynek, służący do operacji na wybranych bitach bajtu, nazywa się maską. AND zeruje te bity rejestru, których odpowiedniki w masce są zerami, resztę pozostawia bez zmian. ORA ustawia (na 1) te bity, których odpowiedniki w masce są jedynkami, a pozostałe się nie zmieniają. EOR natomiast zamienia zera na jedynki, a jedynki na zera w tych miejscach, gdzie bity maski są jedynkami. O tych bitach argumentu, które chronione są przed zmianą, mówimy, że są "zamaskowane". Oczywiście, ze względu na symetrię operacji logicznych, nie jest ważne, czy właściwy argument jest w pamięci, a maska w akumulatorze, czy na odwrót. Wymienione tu rozkazy wpływają na stan dwóch znaczników: Z jest ustawiony, gdy wszystkie bity wyniku są zerami, a do N kopiuje się najstarszy bit wyniku. Zwykle, zamiast definiować dwie maski dla jednego bitu, zadowalamy się jedną:
STER_A EQU 54018
BIT_3  EQU %1000

       LDA STER_A
       AND #255-BIT_3
       STA STER_A
dla włączenia silnika. Zastosowano tu dwa uproszczenia: początkowe zera każdej liczby można pominąć, zaś 256 (dwójkowo %11111111) po odjęciu maski daje jej "negatyw".

Bardzo dowcipnie działa rozkaz BIT, który ustawia znacznik Z tak, jakby wykonana została operacja AND między akumulatorem a komórką pamięci, argumenty wszakże nie ulegają zmianie. Dodatkowo szósty bit bajtu z pamięci przenoszony jest do znacznika V, a siódmy - do N.

W tej grupie wymienia się też zwykle jednoargumentowe rozkazy przesuwające bity, choć mogą też być rozumiane jako dzielenie i mnożenie liczby przez 2. Są cztery takie rozkazy: ASL, LSR, ROL, ROR. Te z nich, które mają na końcu "L", przesuwają bity w lewo, dwa pozostałe - w prawo. Pojedyncze wykonanie rozkazu przesuwa wszystkie bity o jedną pozycję w stosownym kierunku, np. ASL umieszcza na pozycji 1 ten bit, który dotychczas miał numer o, bit 1 przenosi na pozycję 2, itd. Przykładowo
       LDA #%00110101
       ASL @
spowoduje przekształcenie liczby w akumulatorze w %01101010. Na opróżnionej skrajnej pozycji w przypadku rozkazów ASL i LSR umieszczane jest zero, natomiast rozkazy ROL i ROR umieszczają tam dotychczasową wartość znacznika C. Wszystkie cztery rozkazy przenoszą "wychodzący" bit do znacznika C. Symbol "@" oznacza, że argument operacji znajduje się w akumulatorze. Te cztery bowiem (i tylko te) rozkazy mogą odnosić się do komórki pamięci lub do akumulatora.

Co wynika ze znacznika?

   Przedstawić już pora kompletny zestaw znaczników. Zgodnie z miejscem zajmowanym w rejestrze procesora są to:

N V 1 B D I Z C

N, V, Z, C są znacznikami wyniku operacji, natomiast B, D, I opisują tryb pracy procesora. Oto omówienie znaczników:

N - kopia 7. bitu wyniku
V - przeniesienie lub pożyczka pomiędzy 6. i 7. bitem
1 - nieużywany, większość odmian procesora ma tu 1
B - zerowany na skutek przerwania zewnętrznego, poza tym 1
D - tryb dziesiętny wykonywania rozkazów ADC i SBC
I - blokada przyjmowania przerwań IRQ
Z - 1 gdy wszystkie bity wyniku są zerami, kiedy indziej 0
C - przeniesienie z 7. bitu wyniku (lub brak pożyczki przy SBC)

Wyjątkowy wpływ rozkazu BIT na znaczniki opisano wyżej. N i Z są aktualizowane przez wszystkie rozkazy arytmetyczne, logiczne i przesyłające wartość d o rejestru. Znacznik V zmienia się tylko pod wpływem rozkazów ADC, SBC, PLP, BIT. Na znacznik C wpływają tylko: ADC, SBC, PLP, ROL, ROR, ASL, LSR. Należy w szczególności pamiętać, że przesłania z rejestru do pamięci nie zmieniają żadnych znaczników. Każdy z rozkazów skoków warunkowych kieruje się w swym działaniu wartością jakiegoś znacznika:

rozkaz skocz,gdy...
BNE Z=0
BEQ Z=1
BPL N=0
BMI N=1
BCC C=0
BCS C=1
BVC V=0
BVS V=1

Jeszcze o trybach adresowania

Aby wyświetlić napis na ekranie, zastosujemy poznaną już konstrukcję pętli.
EKRAN EQU 48192
      LDY #15
PISZ  LDA #'a'
      STA EKRAN,Y
      DEY
      BPL PISZ
Uwaga: jeżeli komputer był uruchamiany bez wciśniętego klawisza OPTION, etykiecie EKRAN trzeba nadać wartość 40000, a nie 48192. Fakt, że obraz w komputerze ATARI nie ma sztywno przydzielonego obszaru pamięci, komplikuje nieco wyświetlanie, jeśli chcemy, by tekst był widoczny w każdej sytuacji. Aktualny adres pamięci obrazu zawarty jest w komórkach 88 i 89. Można zatem napisać tak:
ADRES EQU 88

      LDY #15
PISZ  LDA #'a'
      STA (ADRES),Y
      DEY
      BPL PISZ
Taki zapis: STA (ADRES).Y oznacza zapis bąjtu z akumulatora pod adres otrzymany ze słowa leżącego pod adresem ADRES, zwiększonego o zawartość rejestru Y. Taki sposób dostępu do pamięci nazywamy adresowaniem pośrednim indeksowym. Pomyślmy jeszcze chwilę o powyższym przykładzie: jeśli np. w 88,89 siedzi adres 20000, to kolejne znaczki zostaną umieszczone pod adresami 20015, 20014, 20013, itd., aż do 20000. W ten sposób możemy operować na adresach nam jawnie nieznanych (znanych tylko komputerowi!). Zwodniczo podobny, ale zgoła różny w działaniu jest tryb adresowania pośredniego z rejestrem indeksowym X.
STA (ADRES,X) (zwróć uwagę na położenie nawiasu!) znajduje adres argumentu w słowie pod adresem o zawartość X dalszym niż ADRES. Załóżmy, że komórki 100 i 101 zawierają liczbę 400, komórki 120 i 121-liczbę 500, w rejestrze X jest 20, w rejestrze Y jest 80.
STA (100,X) odwoła się do komórki o adresie 500
STA (100),Y odwoła się do komórki o adresie 420

Nawias oznacza: weź słowo spod... Przecinek oznacza: dodaj zawartość rejestru... Ostateczny wynik jest adresem argumentu. Część liczbowa tych rozkazów jest liczbą krótką, zapisywaną w jednym bajcie, a zatem słowo zawierające adres musi leżeć między adresem 0 a 255. Ten obszar pamięci nazywa się stroną "zerową". Tryb adresowania (adres,X) jest znikomo pożyteczny, w odróżnieniu od drugiego, stosowanego bardzo często.

Nietrudno zauważyć, że fragment pamięci możliwy do objęcia przy zmianach rejestru Y jest niewielki (co najwyżej 256 bajtów), gdy więc trzeba odwołać się do, powiedzmy, 768 bajtów, robimy to tak:
* adres ekranu
EKRAN  EQU 88

* komórki 204,205
* nie są używane
* przez system
ADRES  EQU 204

*--- kopiowanie adresu
       LDA EKRAN
       STA ADRES
       LDA EKRAN+1
       STA ADRES+1
*--- zapełnianie ekranu
       LDX #3 (bo 3*256=768)
*- pętla po 256 bajtów
L_256  LDY #0

*- pętla po 1 bajcie
L_1    LDA #'X'
       STA (ADRES),Y
       INY  następny bajt
       BNE L_1
       INC ADRES+1
       DEX  następne 256 ?
       BNE L_256
Warto zauważyć, że modyfikować trzeba tylko starszy bajt słowa ADRES, ponieważ zmiany rejestru Y pokrywają cały możliwy zakres zmian młodszego bajtu.

Strony pamięci, strona zerowa

Stroną pamięci nazywamy taki jej obszar, którego adresy mają jednakowy starszy (bardziej znaczący) bajt. Na przykład dla komórek od 256 do 511 starszy bajt adresu jest równy 1, gdy młodszy zmienia się od 0 do 255. Starszy bajt wyznacza więc numer strony, młodszy - numer bajtu na stronie. Jest oczywiście 256 różnych stron, wszak cała pamięć ma 256 * 256 = 65536 bajtów. Ta ze stron, której numer jest równy 0, zwie się zerową. Wiele rozkazów procesora odnosi się właśnie do tej strony. Adres w takich rozkazach zostaje skrócony do jednego bajtu, przez co wykonują się szybciej od tych z pełnymi (długimi) adresami.

Janusz B. Wiśniewski

Dalszy ciąg nastąpi.



Powrót na start | Powrót do spisu treści | Powrót na stronę główną

Pixel 2001