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":
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, 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:
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.
|