Kurs Assemblera cz. 4

ASEMBLER 6502
KOMPUTER – ZNACZY LICZYDŁO!

Jak zdążyłem już nadmienić, słowo computer w języku angielskim oznacza mniej więcej tyle co liczydło. Sugerowałoby to istnienie możliwości liczenia na naszej ma­szynie. Jak już zapewne wiesz, liczenie w BASIC problemem nie jest. Wiemy też, że wszystko, co da się zrobić w BASIC, da się też zrobić w asemblerze. l rzeczywiście, do­dawać w asemblerze można i temu też po­święcimy dzisiejsze spotkanie.

Nasz komputer jest jednak zbyt cwana ma­szyna, by po prostu wziąć dwie liczby, dodać je i wstawić w jakieś miejsce, z którego łatwo je będzie wyciągnąć. Operacja dodawania przebiega w C-64 w następujący sposób: komputer bierze podaną mu liczbę, traktując ją jako argument lub też adres, pod którym szukać ma argumentu. Po ustaleniu, czym w końcu jest argument, dodaje do niego aktual­ną zawartość akumulatora i UWAGA! – aktualny stan flagi Carry (przeniesienie). Otrzy­maną liczbę wstawia do akumulatora i odpowiednio przestawia flagi Carry (przeniesie­nie), Zero (zero), Negative (ujemne) i oVer-flow (przepełnienie).

Instrukcja, o której ciągle mówimy, nazywa się ADC. Tłumaczy się to na angielski ADC willi Carry, zaś na polski: dodawanie z prze­niesieniem. Specjalną cechą dodawania z przeniesieniem jest fakt, że do wyniku działa­nia dodaje się jeszcze zawartość flagi C. Jeśli więc chcemy, by wynikiem dodawania było to, co zwykle, bez żadnych dodatkowych sensacji, musimy wyzerować znacznik C roz­kazem CLC. ADC działa więc tak:

	ASEMBLER        MONITOR 
*=10000
LDA #$02 2710 LDA #$02
CLC 2712 CLC
ADC #$02 2713 ADC #$02
STA $2800 2715 STA $2800
BRK 2718 BRK

Jeśli zadasz sobie trud wpisania i urucho­mienia programu (G2710, SYS 10000 albo strzałka w lewo, 3 i S), to komputer zada so­bie trud dodania dwóch do dwóch i wstawie­nia wyniku do komórki $2800, czyli (10240). Po zakończeniu pracy programu (chyba nie­zauważalnie krótkiej) możemy sprawdzić efekty za pomocą np. PRINT PEEK (10240). Jest4? Powinno…

Czym jednak byłoby dodawanie bez odro­biny odejmowania? Na szczęście, 6502 ma także odejmowanie. Jest za nie odpowiedzial­na instrukcja SBC (SuBstract with Carry czyli odejmowanie z przeniesieniem). Działa ona dokładnie odwrotnie niż ADC. Odwrotnie też interpretuje wskaźnik C. To znaczy od zawar­tości akumulatora odejmuje argument a nas­tępnie odejmuje jeszcze 1, jeśli C jest równy zeru, zaś jeśli flaga C jest zapalona, ta dodat­kowa liczba odejmowana nie jest. Musimy to więc pamiętać, by znacznik przeniesienia za­palić rozkazem SEC (ciągle więc odwrotnie niż w dodawaniu). Dla przykładu odejmijmy więc od 10 liczbę 7, którą uprzednio wstawi­my do komórki $2800. Wynik wstawimy pod adres $2801.

	ASEMBLER          MONITOR 
*=10000
LDA #7 A2710 LDA #$07
STA $2800 A2712 STA $2800
SEC A2715 SEC
LDA #10 A2716 LDA #$0a
SBC $2800 A2718 SBC $2800
STA $2801 A271B STA $2801
BRK A271E BRK

Sprawdźmy teraz wynik w komórce 10241. Powinno być 3. Dla eksperymentu zmień jeszcze rozkaz SEC na CLC. I co? Jest 2? OK. Czy do tej pory nie zaskoczył, zirytował lub choćby zdziwił Cię fakt, że przy dodawaniu i odejmowaniu zawsze używany jest wskaźnik przeniesienia? Wskaźnik ten służy nam do uproszczenia wykonywanych operacji pod­czas dodawania/odejmowania dwubajtowe-go. Skomplikowanie dodawania jednobajtowego jest nieznaczne – wstawiamy tylko je­den rozkaz, który byłby zbędny, gdyby istniało dodawanie bez przeniesienia. Natomiast go­rzej byłoby, gdyby nie istniało dodawanie z przeniesieniem. Dodawanie dwubajtowe roz­szerzyłoby się ponad miarę – trzeba by do­dawać skoki warunkowe, odniesienia do flagi C, jeszcze jedno dodawanie, gdyby flaga ta była ustawiona. Oczywiście, zawsze można by powiedzieć, że projektanci mogli wstawić OBIE te instrukcje. Byłoby to jednak sprzecz­ne z ogólną filozofią procesora (szybki, mała ilość rozkazów). Dzięki temu właśnie, mimo powolniejszego zegara, procesor ten okazał się lepszym od np. Z80, znacznie bardziej skomplikowanego i zagmatwanego a przez to wolniejszego.

Czyli, musimy się po prostu przyzwycza­ić, żeby przed każdym dodawaniem wyzero­wać (CLC), a odejmowaniem, ustawić (SEC) znacznik przeniesienia, l już. Przeniesienie jest bardzo przydatne gdy dodajemy do siebie dwie liczby dwubajtowe (ew. przewidujemy, że wynik naszej operacji przekroczy 255). Musimy wówczas postąpić tak:

  1. Pierwszy ze składników dzielimy na młodszy i starszy bajt. Mł. wstawiamy do komórki $2800, st. do $2801.
  2. Drugi składnik również dzielimy na bajty. Młodszy kierujemy do $2802 a starszy ? do $2803.
  3. Wygaszamy wskaźnik przeniesienia (CLC).
  4. Dodajemy zawartość komórki $2800 do zawartości komórki $2802 a wynik odsyła­my do $2804.
  5. Dodajemy $2801 do tego, co znajdziemy w komórce $2803. Wynik trafia do $2805.

Wtedy wynik składa się z dwóch bajtów ? młodszego ($2804) i starszego ($2805). Zna­ną już nam metodą przerabiamy to na liczbę dwubajtową i odchodzimy w szczęściu. Przedtem jednak zwróć uwagę, że przed dru­gim dodawaniem wcale nie zmienialiśmy flagi C. Jeżeli wynik pierwszego dodawania bę­dzie mniejszy niż $ff (255), to znacznik C po-ostanie zgaszony i druga operacja przebiega Normalnie. Jeżeli jednak liczba ta zostanie przekroczona, to ?w pamięci” (jak przy pisemnym dodawaniu) zostaje 1, które trzeba dorzucić do dodawania wyższego rzędu. ?Pamięcią” tą, którą na papierze symbolizuje zazwyczaj jedynka w kółeczku, jest tutaj właśnie C. Jeżeli pierwsze dodawanie je ustawi, drugie będzie musiało je uwzględnić. Może ę też zdarzyć, że także po drugim dodawaniu znacznik C będzie zapalony. Wtedy musimy traktować wynik jako liczbę trzybajtową, której siedemnastym bitem jest flaga przeniesienia.

Oto zaś program na dodawanie liczb dwubitowych. Polecam go Twojej szczególnej uwadze:


ASEMBLER MONITOR
*=10000
CLC A2710 CLC
LDA $2800 A2711 LDA $2800
ADC $2802 A2714 ADC $2802
STA $2804 A2717 STA $2804
LDA $2801 A271A LDA $2801
ADC $2803 A271D ADC $2803
STA $2805 A2720 STA $2805
BRK A2721 BRK

Po udanym wpisaniu i przetestowaniu programu proponuję choć chwilę poeksperymentować i zbadać, czy wszystko się zgadza. Jeśli tak – przystąp do napisania analogicznego programu wykonującego operację odejmowania dwubajtowego. Ha! Prowadzimy tu przecież w końcu kurs PROGRAMOWANIA a nie tylko uważnego przepisywania programów. Mam nadzieję, że zadanie to zbytnio e przeciąży Twojego napiętego harmono­gramu dnia i już za miesiąc porozmawiamy o zwijaniu i rolowaniu bitów.

Dodaj komentarz

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