Dufam ze ste domacu ulohu zvladli bez problemov a podarilo sa vam skomprimovat nielen nuly, ale aj ine hodnoty bajtov. Lenze takato komprimacia, aku sme spominali v minulej lekcii ma jednu nevyhodu - komprimuje vzdy iba jednu konkretnu hodnotu bajtov a ostatne si nevsima. Pritom v praxi sa prave velmi casto vyskytuju bloky rovnakych bajtov, pricom kazdy blok obsahuje ine bajty (napriiiiiiiiiiklad v takyyyyyyyyychto textoch).
Istym riesenim by bolo spravit 256 komprimacnych a dekomprimacnych rutin (na kazdu hodnotu bajtu jednu), ale aj sami uznate, ze taketo riesenie je trochu pritiahnute za vlasy. Ovela lepsie je vytvorit si jednu rutinku, ktora bude univerzalna a bude komrpimovat bloky rovnakych bajtov s akymikolvek hodnotami.
K tomu budeme musiet vyriesit dva problemy. Kedze komprimujeme bloky s lubovolnou hodnotou bajtov, budeme okrem poctu rovnakych bajtov a informacie indentifikujucej tento pocet este potrebovat aj informaciu o hodnote samotnych bajtov. Inymi slovami - za znackovym bajtom musime okrem bajtu urcujuceho pocet este zapisat aj bajt, ktory sa vyskytoval viac krat za sebou.
Nasa dnesna komprimacna rutinka teda bude komprimovat blok pameti tak, ze bude zistovat, ci sa v temto bloku nenachadzaju za sebou rovnake bajty. Akonahle zisti vyskyt aspon dvoch za sebou rovnakych bajtov, zapise do skomprimovaneho suboru znackovy bajt, za nim o ake rovnake bajty to vlastne islo a ako treti bajt sa zapise pocet tychto rovnakych bajtov.
Druhy problem spociva v tom, ze ak sa nahodou v zdrojovom bloku pameti nachadza znackovy bajt, nesmieme ho len tak jednoducho presunut do skomprimovaneho bloku, lebo si potom dekomprimacna rutinka bude mysliet, ze v zdrojovom bloku sa nechadzali za sebou rovnake bajty a tym padom nebude dekomprimovat spravne. Nasa rutinka to riesi tak, ze znackovy bajt chape ako blok rovnakych bajtov, ktory obsahuje prave jeden bajt (ten nas znackovy) a do skomrimovaneho bloku ulozi znackovy bajt [ako znacku], potom za neho zase ten isty znackovy bajt [teraz uz ako samotny bajt] a napokon pocet bajtov [cislo 1]. Kedze tymto opatrenim spotrebujeme na ulozenie jedneho bajtu az tri bajty, je preto vhodne ako znackovy bajt volit ten bajt, ktory ma v danom zdrojovom bloku pameti co najmensi pocet vyskytov.
znacka | = | #8e | priklad znackoveho bajtu |
Komprimacna rutinka: | |||
pack | ld | hl,#4000 | priklad adresy povodneho bloku |
ld | de,#9000 | priklad cielovej adresy | |
ld | bc,#1800 | priklad dlzky bloky | |
kom | ld | a,(hl) | vezmeme bajt |
inc | hl | a s dalsim bajtom | |
cp | (hl) | ho porovname | |
jr | z,pakuj | ak je rovnaky, komprimujeme | |
cp | znacka | inak zistime ci je to znacka | |
jr | nz,nepak | ak nie tak skok | |
ld | (de),a | ulozime znackovy bajt [znacka] | |
inc | de | za neho zase | |
ld | (de),a | ulozime ten isty bajt [bajt] | |
inc | de | dalej | |
ld | a,#01 | ulozime jednotku [pocet] | |
nepak | ld | (de),a | ulozime dany bajt |
inc | de | zmenime pocitadla | |
dec | bc | a skontrolujeme | |
ld | a,b | ci sme uz spracovali | |
or | c | cely blok | |
jr | nz,kom | ak nie tak pokracujeme | |
ret | ak ano tak navrat. | ||
pakuj | ld | xh,#00 | zaciatocne nastavenie pocitadla |
dec | hl | predbezna korekcia ukazovatela | |
paklop | inc | xh | zvecsime pocitadlo bajtov |
inc | hl | ukazovatele presunieme | |
dec | bc | na dalsi bajt | |
jr | z,moc1 | ak pretieklo pocitadlo tak skok | |
ex | af,af | uschovame akumulator | |
ld | a,b | aby sme mohli skontrolovat | |
or | c | ci sme uz spracovali cely blok | |
jr | z,moc2 | ak ano tak tiez skok | |
ex | af,af | ak nie tak skontrolujeme | |
cp | (hl) | ci aj dalsi bajt je taky isty | |
jr | z,paklop | ak ano tak tieto bajty pocitame dalej | |
moc1 | ex | af,af | Ak skoncime pocitanie rovnakych bajtov |
moc2 | ld | a,znacka | tak do skoprimovaneho bloku |
ld | (de),a | ulozime znackovy bajt [znacka] | |
inc | de | za neho potom | |
ex | af,af | ulozime hodnotu bajtov | |
ld | (de),a | ktore sme pocitali [bajt] | |
inc | de | dalej ulozime | |
ld | a,xh | stav naseho | |
ld | (de),a | pocitadla [pocet] | |
inc | de | napokon upravime ukazovatel | |
ld | a,b | a skontrolujeme ci sme uz | |
or | c | spracovali cely blok | |
jr | nz,kom | ak nie tak pokracujeme | |
ret | ak ano tak navrat. | ||
Dekomprimacna rutinka: | |||
unpack | ld | hl,#9000 | priklad adresy skomprimovaneho bloku |
ld | de,#4000 | priklad adresy povodneho bloku | |
ld | bc,#1800 | priklad dlzky povodneho bloku | |
dek | ld | a,(hl) | precitame bajt |
cp | znacka | je to znacka ? | |
jr | z,depak | ak ano budeme dekomprimovat | |
ld | (de),a | inak ho iba normalne ulozime | |
inc | de | upravime ukazovatele | |
cpi | ak sme spracovali uz cely blok | ||
ret | po | tak sa vratime, | |
jr | dek | inak pokracujeme dalsim bajtov. | |
depak | inc | hl | Za znackovym bajtom |
ld | a,(hl) | bude nasledovat hodnota bajtu | |
inc | hl | a za hodnotou | |
ex | af,af | (uschovame si hodnotu) | |
ld | a,(hl) | nasleduje pocet | |
ld | xh,a | pocet ulozime do pocitadla | |
ex | af,af | (obnovime hodnotu) | |
inc | hl | este mala korekcia ukazovatela | |
deklop | ld | (de),a | ulozime do bloku hodnotu bajtov |
inc | de | ukazovatel na dalsiu adresu | |
dec | bc | zmensime pocitadlo | |
ex | af,af | a skontrolujeme ci | |
ld | a,b | sme uz dekomprimovali | |
or | c | vsetko co sme chceli | |
ret | z | ak ano tak navrat | |
ex | af,af | ak nie tak pokracujeme | |
dec | xh | zmensime pocitadlo, je uz nulove ? | |
jr | nz,deklop | ak este nie dekomprimujeme dalej | |
jr | dek | inak pokracujeme dalsimi bajtami. |
Vas Busy.