Komprimacia "kolko - bajt"

   Minule sme si vynimocne ukazali najprv dekomprimacnu rutinku s tym, ze ste si mali na domacu ulohu rozmysliet ako asi bude vyzerat a co vsetko musi vykonat komprimacna rutinka. Uloha to bola pomerne zlozita, ale ja verim, ze ste ju zvladli bez vecsich problemov.

   Nasa komprimacna rutinka sa musi najprv pozriet ci za sebou nasleduju aspon tri rovnake bajty. Ak nasleduju tak ich musi spocitat. Ak by ich bolo viac ako 128, musi prestat pocitat, pretoze do pocitadla poctu rovnakych bajtov by sa vyssie cislo nevoslo. Potom ulozi pocet tychto bajtov do specialneho bajtu (ktoreho dolnych 7 bitov sluzi na uchovanie poctu bajtov a siedmy bit tohto bajtu bude 1) a cely algoritmus sa opakuje od zaciatku. Ale ak za sebou nenasleduju tri rovnake bajty, tak potom musi spocitat kolko ich nasleduje nerovnakych. To znamena ze akonahle narazi na prve tri rovnake bajty, tie uz nesmie zaratat do poctu. Tiez musi kontrolovat pocitanie bajtov iba do hodnoty 128. Potom aj v tomto pripade ulozi pocet do toho specialneho bajtu (siedmy bit bude 0) a cely algoritmus ide odznova. Samozrejme ze pocas tohto vsetkeho treba testovat ci sme uz spracovali cely povodny blok - ak ano potom treba cinnost algoritmu vhodne ukoncit.

   Preco prave tri rovnake bajty ? Pretoze az komprimacia troch rovnakych bajtov prinesie uzitok - skratenie skomprimovaneho bloku.

   Ako vidime, algoritmus komprimacie je pomerne jednoduchy. Avsak jeho realizacia uz bude jednoducha trochu menej... Ale ked si vsimneme nasu dnesnu rutinku a pozorne si ju prejdeme tak urcite nebude problem pochopit do detailov ako pracuje.

   Urcite ste si v minulej lekcii vsimli ze v popise rutinky sa spominaju dve pocitadla. Presne take iste pocitadla su aj v dnesnej rutinke. Prve, nazvane hlavne pocitadlo sluzi na odpocitavanie poctu bajtov - kolko nam este zostava dekomprimovat alebo skomprimovat. Je to vlastne pocitadlo dlzky povodneho bloku. Druhe pocitadlo je nazvane minipocitadlo a sluzi na odpocitavanie hodnoty v nizsich siedmich bitoch specialneho bajtu (pri dekomprimacii) alebo na vypocet hodnoty tychto siedmych bitov (pri komprimacii).

kom ld hl,#4000 zaciatok bloku 
 ld de,#8000 kam ulozit tento blok 
 ld ix,#1b00 dlzka bloku 
rec ld a,xh kontrola hl. pocitadla na nulu 
 or xl ak je pocitadlo nulove 
 ret tak hotovo a navrat 
 ld b,#80 inicializacia minipocitadla 
 call zisti su tu aspon 3 bajty rovnake ? 
 jr nz,nek ak nie tak sa nebude komprimovat 
 inc de ale ak ano tak ich treba spocitat 
 ld (de),a ulozenie hodnoty samotneho bajtu 
 dec de DE bude ukazovat na "pocet" bajtov 
kk2 inc hl ukazovatel bloku na dalsi bajt 
 dec ix a zmensenie hlavneho pocitadla 
 ex af,af uschova hodnoty bajtu 
 ld a,xh nedosli sme medzitym na koniec 
 or xl zdrojoveho bloku ? 
 jr z,kk3 ak ano tak prestaneme pocitat bajty 
 ex af,af obnova hodnoty bajtu 
 inc zvecsenie minipocitadla, ak pretieklo 
 jr z,kk3 tak potom tiez prestaneme pocitat 
 cp (hl) porovnanie ci este nasleduje taky 
 jr z,kk2 isty bajt, ak ano pocitame dalej 
kk3 ld a,b bajty sme dopocitali, preto teraz 
 or #80 treba ulozit stav minipocitadla 
 ld (de),a do skomprimovaneho bloku 
 inc de presun ukazovatela 
 inc de na volnu poziciu 
 jr rec a znovu skok do hlavnej slucky 
   Ak sa nenasli rovnake bajty: 
nek ld (pocet+1),de uschova pozicie minipocitadla 
 inc de a ukazovatel na volnu poziciu 
kk4 call zisti idu za sebou tri rovnake bajty ? 
 jr z,kk5 ak ano treba skocit 
 ld (de),a ulozenie jedneho bajtu 
 inc de posun ukazovatelov 
 inc hl pre ukladanie roznych bajtov 
 dec ix test ci sme uz presli cely 
 ld a,xh blok 
 or xl ak ano tak tiez musime skoncit 
 jr z,kk5 ukladanie roznych bajtov 
 inc zvecsime minipocitadlo 
 jr nz,kk4 ak pretieklo, tiez musime skoncit 
kk5 ld a,b koniec ukladania roznych bajtov - 
 and #7f ulozenie stavu pocitadla roznych 
pocet ld (#5555),a bajtov do skomprimovaneho bloku 
 jr rec a skok na zaciatok hlavnej slucky 
   Test ci sa v bloku nachadzaju 
zisti ld a,(hl) za sebou tri rovnake bajty 
 inc hl - vezme prvy bajt 
 cp (hl) porovna s druhym 
 jr nz,zzno ak nezhoda tak hned koniec 
 inc hl ak zhoda tak sa este 
 cp (hl) porovna s tretim 
 dec hl Obnova zaciatocneho stavu 
zzno dec hl ukazovatela do bloku 
 ret  a navrat 

   Ako vidime aj v tejto rutinke sa dlzka povodneho bloku netradicne vklada do registra IX. Ak chcete mat dlzku v inom registri, urcite uz viete co mate robit (ak nie pozrite sa do minulej lekcie).

   Vsimnime si v rutinke jednu zaujimavu vec: instrukciu LD (pocet+1),DE. Na tejto samotnej instrukcii este nie je nic zaujimave. Ale teraz sa pozrime na navestie "pocet" - a vidime ze je v programe a ukazuje na instrukciu LD (#5555),A !!! Tato instrukcia ma operacny kod dlhy presne jeden bajt a za tymto operacnym kodom nasleduje dost nepochopitelne cislo #5555. Ked si lepsie vsimneme prvu instrukciu LD (pocet+1),DE zistime ze tato instrukcia zapisuje register DE prave na tu adresu pameti, kde sa nachadza toto nepochopitelne cislo. Cize vlastne pri pisani rutinky je uplne jedno aku hodnotu napisete namiesto #5555, aj tak sa tato hodnota v priebehu prace programu modifikuje.

   Prave toto zaraduje nasu rutinku do triedy tzv. "samomodifikujucich sa programov" - to znamena ze kod rutinky sa v priebehu prace meni. To ale tiez znamena ze tato rutinka by nemohla funguvat keby bola v romke alebo v ramke so zakazanym zapisom. O samomodifikujucich sa programoch este budeme pisat v niektorej z nasledujucich lekcii.

Vas Busy.

Nazad / back , predchadzajuca a dalsia lekcia