Predpokladam, ze domacu ulohu z minulej lekcie sa vam bez
problemov podarilo vyriesit. Uloha znela: Preco je "ZLO" mensie
ako "zlo" ?
Riesenie je este jednoduchsie ako samotna uloha. Vsimnite si,
ze ASCII kody malych pismen maju vyssie hodnoty ako ASCII kody
velkych pismen. Nas porovnavaci program porovnaval slova tak, ze
porovnaval ASCII kody jednotlivych pismen. Prve pismeno "z"
slova "zlo" ma kod #7A a prve pismeno slova "ZLO" ma kod #5A.
Nas program porovnal najprv prve bajty retazcov - cize #7A a
#5A. Zistil nezhodu a preto sa hned vratil s tym, ze retazec
zacinajuci na #7A je "vecsi". Tym nam vlastne nepriamo ukazal,
ze "zlo" je vecsie ako "ZLO".
Ked sa dobre pozrieme na instrukcny subor Z80 uvidime, ze
obsahuje plno roznych instrukcii na scitanie a odcitanie. Lenze
v matematike existuje este cely rad dalsich operacii: nasobenie,
delenie, umocnovanie, goniometricke funkcie, derivacie,
integraly a mnohe ine... S integralmi sa (zatial) zaoberat
nebudeme, lebo to by bolo (zatial) nad nase sily.
Ale skusme si naprogramovat take nasobenie. To je operacia,
ktoru pravdepodobne budeme po scitani a odcitani najcastejsie
potrebovat.
Vsimnime si najprv matematicku definicu nasobenia. Vynasobit
cislo M cislom N znamena to iste ako keby sme k nule N-krat
pripocitali cislo M. Tolko definicia. Teraz si polozme otazku.
Mozme tuto definiciu nejak vyuzit ? N-krat nieco vykonat vieme
(pouzijeme slucku) a pripocitavat tiez vieme, to znamena, ze
tuto definiciu mozme priamo realizovat ! Takze podme na to.
Zvolme si, ze budeme nasobit dve osembitove cisla v rozsahu 0
az 255. Tym sme si zaroven zvolili aj rozsah vysledku: najmensi
vysledok bude nula (0*0), najvecsi bude 65025 (255*255). Cize
vysledok bude 16-bitove cislo. Na to musime pametat pri
vytvarani rutinky.
Slucka, ktora zabezpeci opakovanie scitavania, musi vediet
prebehnut aj nula-krat (ak N=0). Preto treba hned na zaciatku
testovat, ci je N nulove. Ulozme si toto nase N do registra A
(lebo ten sa najlahsie testuje na nulu). Po teste vykoname to
pricitanie a slucku opakujeme N-1 krat. Opakovanie slucky N-1
krat sa nam najlepsie spravi tak, ze skocime znovu na zaciatok
slucky s cislo N zmensenym o jednotku. Nasa slucka bude vyzerat
takto:
ld | a,N | |
slucka | and | a |
ret | z | |
(pricitanie) | ||
dec | a | |
jr | slucka |
Vsimnime si sposob testovania akumulatora, ci je v nom nula. Deje sa to tak, ze sa vykona bitovy AND akumulatora so samym sebou. Vysledok bude teda ten isty ako povodny operand (nezmeni nam to akumulator), ale pre nas je dolezite, ze ked boli vsetky bity akumulatora nulove (to znamena N=0) tak sa nastavi zero a instrukcia RET Z vtedy ukonci nasu rutinku. Mohli by sme to testovat aj instrukciou CP #00, ale sposob pomocou AND A je rychlejsi a zabera o jeden bajt pamete menej.
Podme teraz vyriesit to pricitanie. Ako sme uz zistili,
vysledok by mal byt 16-bitovy. A hned sa nam ponuka instrukcia
ADD HL,DE. Skusme ju dako vyuzit. Kedze vysledok tejto
instrukcie je v registri HL, zvolme si, ze aj vysledok nasho
programu bude v HL. No a neostava nam uz nic ine, len do
registra DE vlozit cislo M. Najjednoduchsie by to slo spravit
instrukciou LD DE,M - ale ma to hacik. Totiz operand tejto
instrukcie je 16-bitovy, ale nasa hodnota M je iba osembitova.
Tento hacik nas zatial nemusi trapit, pretoze asembler nam to
prelozi tak, ze nizsi bajt, ktory sa zapise do E bude to nase M
a vyssi bajt ktory pojde do D bude nula.
Tym sme si vyriesili aj to pricitanie a mozme prikrocit k
samotnej rutinke.
HOP ! Na nieco sme ale zabudli. Vsimnime si este raz definiciu:
"...ako keby sme K NULE n-krat..." Na zacatku musime regster HL
vynulovat, aby tam nezostali dake "zbytky" z predchadzajucej
cinnosti. Nulovanie by sme mohli urobit instrukciou LD HL,0 ,
ale mam pre vas riesenie, ktore je rychlejsie a zabera menej
pameti. Co keby sme vyuzili tu nulu, ktora je v registri D a
skusili ju vlozit do HL ? Kedze nemame instrukciu LD HL,D,
musime pouzit dve instrukcie: LD H,D a LD L,D.
Kompletny program na nasobenie bude vyzerat takto:
ld | de,M | Cislo M (osembitove) | |
ld | a,N | Cislo N (osembitove) | |
ld | h,d | Vynulovanie HL | |
ld | l,d | ||
slucka | and | a | Test A=0 ? |
ret | z | Ak ano tak koniec | |
add | hl,de | Ak nie tak pripocitaj | |
dec | a | N-krat | |
jr | slucka | vykonavaj slucku. |
Vysledok nasobenia bude ulozeny v registri HL.
Ako uz byva nasim dobrym zvykom, nasleduje domaca uloha. Skuste
podobnym sposobom realizovat rutinku, ktora bude delit dve
cisla (16-bitove 8-bitovym). Pomocka: Robte to postupnym
odcitanim a pouzite instrukciu SBC HL,DE.
Uloha to nie je lahka (ale ani tazka) a asi budete musiet
trosku popremyslat, ale ja verim, ze na to napokon pridete.
Vas Busy.