Zaplnenie oblasti pamete

   Pred tym, ako zacneme naostro, este niekolko malych poznamok.

   Vsetky ukazky strojovych rutin s ktorymi sa tu stretneme, su po syntaktickej stranke pisane tak, aby ste ich mohli bez akychkolvek uprav rovno prepisat do znameho ladiaceho systemu MRS - verzie 07 a vyssich. Tyka sa to najme sposobu pisania navesti, operandov instrukcii a niekorych specifickych pseudoinstrucii.
   Rutinky budu urcene pre pocitac ZX Spectrum a s nim kompatibilne typy, ale niekore jednoduchsie rutinky budete moct vyuzit aj na inych pocitacoch s procesorom Z80.
   Ak nepochopite, ako nejaka rutinka pracuje ani po stodvadsiatom osmom precitani, nezufajte ale jednoducho si povedzte, ze proste nejak funguje a vratte sa k nej o nejaky cas, ked budete mudrejsi a skusenejsi. Ak ani potom nepochopite cinnost rutinky, cely tento cyklus opakujte.
   Samozrejme mozete do redakcie pisat akekolvek pripomienky a dotazy ohladne tohto serialu. Napriklad ak sa vam bude zdat prilis jednoduchy alebo prilis narocny, ak vas bude specialne zaujmat nejaky problem, alebo ak ani po stodvadsiatom osmom opakovani vyssie spominaneho cyklu nepochopite cinnost dakej rutinky a budete chciet, aby bola vysvetlena podrobnejsie. Ak sa rozhodnete napisat, oznacte list heslom "Programujeme v assembleri II". Zvlast uvitame kriticke dopisy, ktore budu obsahovat nejake navrhy na zlepsene tohto serialu.

   No a mozeme zacat naostro.

   Jednym z najjednoduchsich problemov v strojovom kode je presunut blok pameti dlhy len bajtov z adresy ad1 na adresu ad2. Ten, kto pozorne sledoval v minulych cislach Bitu serial "Programovanie v strojovom kode", hned vie, ze tento problem riesi instrukcia LDIR. Staci jej len do vhodnych registrov vlozit tieto udaje. Takze kompletny program na kopirovanie bloku bude vyzerat takto:

copy ld hl,ad1 odkial ho treba presunut 
 ld de,ad2 kam ho treba presunut 
 ld bc,len dlzka bloku 
 ldir  samotne skopirovanie 
 ret  a nakoniec navrat. 

   Instrukcia ret zabezpeci navrat do hlavneho programu, z ktoreho ste tuto rutinku zavolali instrukciou call copy alebo do nejakeho monitora (napriklad debugger v systeme MRS), ak ste ju volali z tohto monitora alebo pripadne do basicu, ak ste ju volali pomocou USR copy.
   Ak by ste chceli skopirovat blok o nulovej dlzke, narazili by ste na isty problem. Instrukcia LDIR totiz nulu v registri BC chape ako hodnotu 65536 a aj tak dlhy blok sa bude snazit skopirovat. No a ten problem je v tom, ze vam moze poskodit ine programy, ktore mate v pameti (napriklad ten monitor).

   Skusme teraz vymysliet rutinku, ktora nebude blok kopirovat, ale ho zmaze, presnejsie povedane pametovu oblast od adresy add s dlzkou len zaplny bajtami s hodnotou byte. Na prvy pohlad sa zda zmazane bloku jednoduchsie ako jeho skopirovanie. Ale na druhy pohlad zistime, ze neexistuje instrukcia ktora by priamo vykonavala tuto cinnost.
   Len tak na pripomenutie sa pozrime, ako vlastne pracuje instrukcia LDIR. Vezme prvy bajt z adresy v registri HL, potom tento bajt ulozi naspet do pameti, ale na adresu v registri DE. Nakoniec obsahy registrov HL a DE zvecsi o 1, BC zmensi a ak sa este BC nerovna nule, znovu zopakuje celu tuto cinnost.
   Co sa ale stane, ak hodnota v registri DE bude prave o 1 vecsia ako v HL ? Vezme sa bajt z adresy HL, ulozi sa na adresu DE, potom sa prislusne zmenia hodnoty registrov a ak BC nie je este nulove, cyklus sa opakuje. Nech este nie je nulove. Znovu sa vezme bajt z adresy HL a ulozi sa na adresu DE... Stop ! Lenze ten bajt, ktory sa teraz premiestnil, je vlastne presne ten, co sme premiestnili v predchadzajucom cykle. No a v kazdom dalsom cykle sa potom prenesie ten isty bajt, co v cykle tesne pred nim. Toto sposobi "rozkopirovanie" jedneho bajtu po celej dlzke bloku.
   No a tak rutinka na zmazanie bloku moze vyzerat nejak takto:

zmaz ld hl,add zaciatok bloku 
 ld de,add+1 zaciatok zvecseny o jednu 
 ld bc,len-1 dlzka bloku zmensena o jednu 
 ld (hl),byte ulozenie prveho bajtu 
 ldir  skopirovanie dalsich bajtov 
 ret   

   Vsimnite si, ze do registra BC sa pise dlzka bloku zmensena o jednotku. Je to tak preto, lebo prvy bajt bloku ulozi instrukcia "ld (hl),byte" a preto ho samotna instrukcia LDIR uz nemusi ukladat.
   Kedze prvy bajt bloku sa uklada natvrdo a instrukcia LDIR vzdy skopiruje aspon jeden bajt, je tato rutinka schopna mazat bloky o dlzke aspon dva bajty. Co by sa stalo, keby sme aj napriek tomu za hodnotu len dosadili jednotku ? Vsimnime si, ze v registri BC je pri vstupe do instrukcie LDIR hodnota len-1. No a z predchadzajuceho prikladu uz vieme, co sa vtedy stane. Skopiruje sa (a teda vlastne zmaze) 65536 bajtov...
   Keby ste nahodou za len dosadili nulu, potom v BC bude -1, co predstavuje hodnotu 65535 a tolko bajtov sa aj vtedy zmaze. Takze je to prakticky to iste...

Vas Busy.

Nazad / back , predchadzajuca a dalsia lekcia