Komprimacia so znackovym bajtom

   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 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 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 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 vsetko co sme chceli 
 ret 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.

Nazad / back , predchadzajuca a dalsia lekcia