[ Pobierz całość w formacie PDF ]
kazy zmniejszenia i zwiększenia stanowią pewną namiastkę odej-
mowania i dodawania. Należy jednak pamiętać, że n i e wpły-
wają one na stan znacznika przeniesienia. Gdy zatem wykonamy
rozkazy
LDX #FE
INX
znacznik C nie sygnalizuje nam, że wynik przekroczył granicę
bajtu. Natomiast możemy to sprawdzić z pomocą znacznika wyniku
zerowego Z, który przybierze wartość 1, ponieważ w rejestrze
X po dodaniu 1 do FF znajdzie się wartość 0.
Również znacznik wyniku ujemnego N reaguje na wyniki zas-
tosowania każdego z opisanych sześciu rozkazów. Jeżeli np. w
rejestrze Y będzie się znajdowała wartość 7F (127 dec) i zas-
tosujemy INY, to znacznik N przybierze wartość 1, bowiem w
arytmetyce ze znakiem 128 ma postać binarną 10000000 i ozna-
cza ... - 128.
Jak widać, znajomość zachowania się znaczników w rejest-
rze P nie jest całkiem prosta, a jest ona dla programującego
w asemblerze niezbędna, ponieważ na niej opiera się poprawne
wykonywanie wszelkich operacji arytmetycznych i logicznych, a
także, co jest szczególnie istotne, sprawdzanie warunków i
wykonywanie na ich podstawie odgałęzień warunkowych. By to
przedstawić w oparciu o przykład, poznajmy wstępnie jeden z
62
ośmiu rozkazów odgałęzień czyli skoków warunkowych:
BNE - branch on non equal to 0 - wykonaj odgałęzienie,
gdy wynik ostatniej operacji nie jest równy zeru.
Pary rozkazów LDX i STX oraz LDY i STY zapewniają rejes-
trom X i Y identyczne możliwości przesyłu, jak LDA i STA aku
mulatorowi. Rozpatrzmy następujący program (dane dec):
SUMA LDX #20 Inicjujemy rejestr X wartością 20
LDA #0 Inicjujemy akumulator wartością 0
STA L Przypisujemy zmiennej L wartość 0
CLC Kasujemy znacznik C przed dodawaniem
CYKL INC L L=L+1
ADC L A=A+L, przez A oznaczamy akumulator
DEX Zmniejszamy X jako licznik pętli o 1
BNE CYKL Powtarzamy cykl, dopóki X nie równa się 0
STA S S=A
Jak działa ten program? Wykonuje on sumowanie wartości L
z zawartością akumulatora, zwiększając L za każdym razem o 1.
Czyni to 20 razy, gdy bowiem zawartość X zmniejszana po każ-
dym cyklu o 1 osiągnie 0,rozkaz BNE przestanie powodować powrót
do etykiety CYKL i ostatni rozkaz przeniesie zawartość akumu-
latora do S ($D2 czyli 210).
Innymi słowy program ten doda kolejne liczby 1+2+3+ ...
+19+20 i w S umieścić sumę liczb całkowitych z tego przedzia-
łu. Skąd my to znamy? Ależ tak, to jest napisany w asemblerze
przykładowy algorytm z punktu 1.6. Warto zwrócić uwagę na dro-
bną, lecz bardzo istotną różnicę. Tam,w Basicu licznik pętli
zwiększaliśmy za każdym razem o 1 i sprawdzaliśmy czy nie prze-
kroczył 20. Tu licznik pętli, rejestr X, zmniejszaliśmy od 20
do 1, bowiem przy X=0 pętla nie została już wykonana. Dzięki
temu nie trzeba było, jak w przypadku zwiększania X, spraw-
dzać, czy wskaznik pętli przekroczył 20. W JM wymagałoby to
dodatkowego, nie poznanego jeszcze rozkazu porównania CPX.
Oszczędziliśmy jego 20-krotnego powtarzania czyli 60 dodatko-
wych cykli rozkazowych. Jest to ważna metoda optymalizacji pę-
tli liczonych w JM.
Zwróćmy na koniec uwagę na istotny brak symetrii funkcji
63
między akumulatorem, a rejestrami X i Y. Akumulator uczestni-
czy w dodawaniach i odejmowaniach oraz gromadzi ich wyniki,
natomiast nie można go zwiększyć ani zmniejszyć o 1 z pomocą
INC lub DEC. W rejestrach X i Y możliwości te przedstawiają
się odwrotnie, dostępne jest zmniejszenie i zwiększenie, nie
można natomiast wprząc tych rejestrów do działań arytmetycz-
nych.
wiczenia
1. Napiszmy na nowo w Basicu program z punktu 1.6 uwzg-
lędniając nowy sposób liczenia pętli.
x 2. Jak zapiszemy w asemblerze poniższy program w Basi-
cu?
10 S=0: FOR I=20 TO 1 STEP -1:S=S+I: NEXT I
3.10 Przesunięcie i obrót bitów
W punkcie 3.1 wspomnieliśmy o rozkazach przesunięcia i o-
brotu bitów oraz wstępnie poznaliśmy rozkaz ASL. Wymieńmy je
wszystkie oraz opiszmy ich rolę.
ASL i LSR- logical shift right - arytmetyczne przesunię-
cie bitów w prawo różnią się tylko kierunkiem przesuwania bi-
tów. Wspólne jest dla nich także to, że bit wypadający z licz-
by zostaje automatycznie przeniesiony do znacznika C. Ten po-
zornie drobny fakt przechowania traconego bitu ma, jak się
przekonamy, duże znaczenie praktyczne. Warto zwrócić uwagę, że
po ASL do C trafia najwyższy bit, a po LSR - najmniej znaczą-
cy.
Powiedzmy, że pod adresem G znajduje się binarna wartość
10000001 czyli 129 dec. Po ASL G liczba przekształci się nas-
tępująco:
ASL 10000001
00000010 C=1
Mówiliśmy wcześniej, że przesunięcie bitów w lewo oznacza
pomnożenie liczby przez 2. Ale w komórce G tego nie widać,
jest tam wartość 3. Możemy jednak wykonać:
64
LDA #0
ASL G
ADC #0
STA G+1
W ten sposób wykonując pozornie bezcelowe dodanie zera
do zera w akumulatorze w rzeczywistości "łapiemy" utracony
bit i teraz w dwóch bajtach G i G+1 nasza liczba jest zachowa-
na z mniej znaczącym bajtem LSB jako pierwszym. Aatwo obli-
czyć, że ma ona wartość 1x256+2, czyli 258, czyli 2x129, o co
chodziło.
Podobnie, a przecież inaczej, przebiega LSR G
LSR 10000001
01000000 C=1
Skrajny prawy bit znalazł się w C. W komórce G znajduje
się 64. Jest to wynik c a ł k o w i t o l i c z b o w e g o
dzielenia G przez 2. W znaczniku C znalazła się reszta. Można
ją przechować w komórce, powiedzmy, R (reszta), ale będzie mia-
ła zupełnie inne znaczenie.
Tę metodą można łatwo mnożyć i dzielić liczby
przez kolejne potęgi 2. Na przykład sekwencja
LSR A
LSR A
LSR A
LSR A
umożliwia szybkie ustalenie wartości pierwszej cyfry hex, gdy
wartość A chcemy przedstawić dwiema cyframi hex.
Można również w prosty sposób mnożyć liczby przez 3. Je-
żeli chcemy wykonać to na liczbie w akumulatorze, trzeba pos-
łużyć się pomocniczą zmienną TEMP
STA TEMP Przechowuje w TEMP zawartość A
ASL A Mnoży A przez 2
CLC
ADC TEMP Ax2+A=Ax3
Nawiasem mówiąc do mnożenia liczby 1-bajtowej przez 256
wystarczą same rozkazy przesłań:
65
LDA G
STA G+1
LDA #0
STA G
Repertuar możliwości mnożenia i dzielenia znacznie roz-
szerzają dwa kolejne rozkazy noszące nazwę obrotu tzn.cyklicz-
nego przesunięcia bitów. Są to:
ROL - rotate bits left, obróć bity w lewo
ROR - rotate bits right, obróć bity w prawo
Różnica w stosunku do poprzednich rozkazów polega na tym,
że ROL i ROR nie tracą również poprzedniej wartości znacznika
C wstawiając ją do zwalniającego się odpowiednio najniższego
i najwyższego bitu. Tak więc w obrocie uczestniczy 9, a nie 8
bitów. Przedstawia to rysunek 3.3.
Znacznik
C
7 6 5 4 3 2 1 0
Rys. 3.3 Obrót bitów w lewo
Oto przykłady wykorzystania ROL i ROR w mnożeniu i dziele-
niu przez 4 liczb dwubajtowych.
ASL G Mnoży przez 2 mniej znaczący bajt
ROL G+1 Wstawia przeniesienie do najniższego bitu w G+1
ASL G Ponownie mnoży mniej znaczący bajt przez 2 ...
ROL G+1 ... i ponownie wstawia przeniesienie.
Rozpatrzmy działanie tego programu na przykładzie liczby:
11000101 00100001
G G+1
Pierwszy, mniej znaczący bajt znajduje się pod G, bardziej
znaczący w następnej komórce. Aączna wartość liczby wynosi
$21C5. Kolejne rozkazy dotyczą za każdym razem jednego bajtu.
Bit "wypadający" do znacznika C zapiszemy w nawiasie. Jego
66
wprowadzenie do G+1 zaznaczymy podkreśleniem. Oto kolejne kro-
ki:
ASL G (1)10001010 00100001 Najwyższy bit G wszedł do C
ROL G+1 10001010 01000011
Bit C został wykorzystany w G+1. Liczba ma teraz wartość
$438A.
ASL G (1)00010100 01000011 Znowu najwyższy bit wszedł do C
ROL G+1 00010100 10000111
Ta sama operacja została powtórzona. Liczba ma wartość
$8714. Jest to wynik poprawny.
Dzielenie przez 4 liczby 2-bajtowej przeprowadzamy podo-
bnie, tylko wobec innych bajtów, z przesunięciem i obrotem bi-
tów w przeciwnym kierunku:
[ Pobierz całość w formacie PDF ]