V minulej lekcii ste dostali netradicnu domacu ulohu - mali ste
zistit, ako pracuje program na vypocet druhej odmocniny.
Podarilo sa vam ju vyriesit ? Ak ano, blahozelam vam a ak nie,
nebudte smutni a radsej si pozrite spravne riesenie:
Pokial chceme vypocitat druhu odmocninu z nejakeho cisla,
zaujma nas iba celociselna cast vysledku a z matematickych
operacii vieme len scitanie a odcitanie, tak potom mozme na toto
pouzit jeden velmi pekny a jednoduchy algoritmus ako stvoreny
pre naprogramovanie v strojovom kode.
Nech mame nejake cislo (dajme tomu ze bude v rozsahu 0 - 65535)
a chceme jeho druhu odmocninu. Podla tohto algoritmu musime
postupne od tohto cisla odcitavat postupne vsetky neparne cisla
pocnuc jednotkou (pokracujuc trojkou, petkou, sedmickou...) az
dovtedy, kym je vysledok este kladny. No a hodnota druhej
odmocniny je prave rovna poctu tychto odcitani. Je to skoro ako
delenie, len s tym rozdielom, ze pri deleni sa odcitava
konstanta, ale tu sa odcitava vzdy ine cislo.
Ako teda funguje nas program ? Na samotne odcitanie pouziva
instrukciu SBC HL,DE a preto treba vynulovat CARRY. Tuto cinnost
vykona logicka instukcia XOR A. Lenze XOR A okrem CARRY vynuluje
aj cely akumulator a to je tu vhodne vyuzite. Akumulator je
pouzity na pocitanie poctu odcitani a preto nam XOR A aj zaroven
zabezpeci inicializaciu pocitadla. DEC A za inicializaciou robi
korekciu vysledku - presne tak isto ako pri deleni. Odcitavane
neparne cisla sa uchovavaju v registri DE. Na zaciatku sa donho
zapise jednotka a po kazdom odcitani sa donho vlozi najblizsie
vyssie neparne cislo - jednoducho sa k nemu pripocita dvojka
(dvakrat INC DE). Potom sa pocitadlo zvecsi o jednotku (INC A) a
otestuje sa, ci je uz vysledok odcitania zaporny alebo este nie.
Ak este nie, cela slucka prebehne znovu (JR NC,...).
Po skonceni programu je v registi A hodnota druhej odmocniny z
cisla, ktore bolo na vstupe do programu v registri HL. Pre
najvecsie mozne cisle v HL (65535) je jeho odmocnina iba 255 a
preto nam staci iba osembitovy rozsah tohto pocitadla.
Doteraz sme sa bavili o tom, ako robit v strojovom kode rozne
jednoduche matematicke vypocty. Vsetky tieto matematicke rutinky
vyzaduju na vstupe nejake cisla v registroch procesora. Lenze sa
tu pred nami objavuje jeden problem - uzivatel nezvykne zadavat
cisla priamo ako binarne hodnoty do registrov, ale ako
postupnost cislic. A prave v tom je kamen urazu. Nase
matematicke rutinky nevedia robit s cislami v tvare postupnosti
cislic. Preto si musime vymysliet program (nazvime ho dcbn -
prevod z dekadickeho tvaru do binarnej hodnoty), ktory nam
skonvertuje cislo napisane ako postupnost cislic do binarnej
hodnoty v registri.
Nech je niekde v pameti od adresy buffer zapisane nase cislo
tak, aby cifry nasledovali za sebou v obvyklom poradi - t.j.
najprv vysie rady a potom nizsie. Jednotlive cifry nech su
reprezentovane klasickymi znakmi v kode ASCII. Nech je toto
cislo (v nasom priklade 32768) ukoncene nejakym znakom, ktory
neprislucha ziadnej cifre (v nasom priklade hviezdicou).
Ako bude pracovat nas program ? Na zaciatku nastavi zaciatocnu
hodnotu cisla na nulu. Vezme prvy znak cisla, zisti ze je to
cifra, preto vynasobi momentalnu hodnotu cisla desiatimi a
pripocita k nej hodnotu tejto cifry. Potom skoci na zaciatok
slucky, kde otestuje dalsi znak. Takto bude postupovat az narazi
na znak *. Zisti ze to nie je ziadna cifra a ukonci svoju
cinnost.
buffer | db | '32768*' | bufer s postupnostou cislic |
dcbn | ld | de,buffer | DE bude ukazovatel do bufera |
ld | hl,#00 | HL bude obsahovat okamzitu hodnotu cisla | |
loop | ld | a,(de) | prevzatie cifry z buferu |
sub | '0' | prepocet kodu znaku na hodnotu cifry | |
ret | c | ak vysla zaporna hodnota, nebola to cifra | |
cp | 10 | ak vysla hodnota viac ako 10, tiez nebola | |
ret | nc | ak to nebola cifra tak bude koniec | |
inc | de | ukazovatel na dalsi znak v buferi | |
add | hl,hl | \ | |
ld | c,l | \ | |
ld | b,h | \ Vynasobenie hodnoty cisla desatimi | |
add | hl,hl | / cize HL = HL * 10 | |
add | hl,hl | / | |
add | hl,bc | / | |
ld | c,a | \ Pripocitanie hodnoty | |
ld | b,#00 | > cifry k samotnej | |
add | hl,bc | / hodnote cisla | |
jr | loop | a znovu pre dalsiu cifru. |
Tentoraz bude domaca uloha pre vas jednoduchsia ako obvykle. Nemusite nic vymyslat ani skumat nezname rutinky, iba si pozorne vsimnite sposob vypoctu hodnoty cifry z ASCII kodu jej znaku a akym sposobom sa register HL nasobi desiatimi.
Vas Busy.