korak Nis
Član broj: 125522 Poruke: 622 *.dynamic.sbb.rs.
|
Ovo je pravo pitanje od vladabajic-a,
U deklaracionom bloku, gde se definicu konstante, varijable, tipovi i t. d. nista se ne gubi u odnosu na klasican asembler. Tablice se definicu kao tipizirane konstante, i vrednost ovih konstanti se smesta u flash. Prednost je to sto ovakva tablica moze imati slozenu strukturu (array, record), a uz podrsku asemblera ima se lak pristup bilo kom podatku u tablici. Tipiziranim konstantama se pristupa kao varijablama. Na primer:
tTab = array[0..3] of record
a : byte;
b : word;
end;
const
Tab : tTab = ((a:1;b:1001),(a:2;b:2002),(a:4;b:4004),(a:8;b:8008));
Adresni deo kojim se pristupa, na primer, trecem elementu polja b je [Tab[2].b]; Ako nije moguc 16-to bitni pristup, vec samo bajt po bajt, onda bi se pristupilo visem pa nizem sa: [Tab[2].b.0] i [Tab[2].b.1];. Kompajler prijavljuje gresku ako: [Tab[2].b.2] jer polje b ima samo 2 bajta. Svaka string konstanta se automatski definise kao tipizirana konstanta. Tako na primer:
const
ss = 'Aca i Maca';
pa se sa [ss[0]] pristupa bajtu duzine stringa, a sa [ss[7]] karakteru 'M'. Dakle nema nikakvih ogranicenja ili dodatnog koda u odnosu na klasican asembler.
Sto se tice iskaznog dela programa, tu ima neznatnih odstupanja. Kod repeat..until petlje nema dodatnog koda jer na primer:
repeat
-
-
until =0;
se prevodi tako sto kompajler zapamti adresu na mestu repeat, a kod until =0 pravi relativni skok na tu adresu ako nije setovan fleg Z. Ili ako se inkrementira dvobajtna varijabla za 1:
var
n : word;
-
-
inc [n.1];
if =0 then inc [n.0];
Prvo se inkrementira nizi bajt za 1, pa se testira fleg Z, i ako je on setovan inkrementira se i visi bajt. Ako Z nije setovano skace se na prvu naredbu iza if. Moze se javiti, nekada, par dodatnih bajtova koda kod koriscenja case..of strukture. Tada se javlja nepotreban skok na prvu naredbu iza tog skoka. Ovo nije zbog lose definicije jezika, vec zbog lose implementacije. Ovo nisam ispravljao, mrzelo me je, a ova struktura je vrlo korisna i mnogo pomaze kod struktura sa visestrukim uslovima. Na primer kada testirate koji je taster pritisnut, i zavisno od toga pozivate odredjenu proceduru. Sigurno se pitas koja varijabla ide iza case. Nijedna, vec samo registar sa kojim se moze vrsiti naredba komparacije. Dakle, pre toga vrednost varijable treba smestiti u takav registar.
Postoji i while..do petlja ali u obliku:
repeat by
-
-
prior
-
until >=0;
Kompajler generise kod kojim se posle repeat by skace na prior gde je asemblerski kod za generisanje uslova za izlazak iz petlje, i ako je on ispunjen odmah se napusta petlja i ne izvrsava kod u telu petlje izmedju repeat by i prior. U suprotnom sve se odigrava kao u obicnor repeat..until petlji.
Procedura se poziva samo navodjenjem imena procedure, a kompajler generise dugacak ili kratak poziv, zavisno od toga koliko je udaljena procedura koja se poziva. Parametri proceduri se mogu proslediti preko registara MCU-a, i tada se procedura deklarise bez formalnih parametara. U okviru procedure mogu da se definisu konstante, tipovi i varijable, i one su lokalne za proceduru. Zavisno od implementacije (a moja je takva) varijable definisane u proceduri su dinamicke i nalaze se na steku. Ovo je je moguce i u klasicnom asembleru, ali je tesko za programera i podlozno greskama, dok je sve to mnogo jednostavnije ako se prepusti kompajleru. Moguce je defklarisati i procedure sa formalnim parametrima kojima se strarni parametri prosledjuju preko steka. Isto je i za funkcije. Tako na primer ako imate funkciju koja mnozi word i word i daje rezultat word, onda mnozenje 3 word varijable i smestanje rezultata u cetvrtu bi bilo:
var
a,b,c,r : word;
-
-
r := MulWord(MulWord(a,b).c);
Postoje i moduli, ali nije dozvoljeno da jedan modul ukljucuje drugi. To nije ni potrebno jer kompajler radi malo drukcije od DELPHI ili TurboPASCAL kompajlera. Naime, kada naidje na listu modula:
uses
ModulA,ModulB,ModulC;
kompajler po redosledu prvo prevede sve module od njihovog pocetka (zaglavlja) pa do simbola (sluzbene reci) implementation. Sve sto je prevedeno je globalno i moze se koristiti kako u glavnom tako i u svim ostalim modulima. Posle toga, po istom redosledu, prevede ostali deo izvornog teksta modula. Ovo nije moguce ni u jednom klasicnom asembleru.
Varijable se automatski rasporedjuju u memoriji. Iza simbola var moze stajati var zeropage sto definise da su varijable, tu definisane, na nultoj strani. Ako je varijabla definisana kao:
var
Port1 : byte absolute 1;
znaci da je Port1 varijabla tipa bajt i da se nalazi na adreso 0x0001.
Makroi su posebna prica, za ciji opis ovde nema mnogo prostora. Oni imaju svoje formalne parametre koji nisu tipizirani. U samom makrou se moze ispitivati tip prosledjenog parametra i zavisno od toga se mogu pozivati razlicite procedure, funkcije ili razlicito generisati kod. Makro moze i vratiti vrednost kroz preddefinisani formalni parametar result (koristi se i u funkcijama). Jedan makro moze da ukljuci drugi makro. U makrou mogu da postoje i labele (oni koji rade u C-u znaju kakvi problemi postoje sa makroima koji imaju labele). Takodje posoji i preddefinisana procedura koja prijavljuje gresku, onako kako to programer definise. Samo jedan mali primer:
macro Pomnozi(a,b);
begin
_if (TypeOf(a) = TypeOf(byte)) and (TypeOf(b) = TypeOf(byte)) then result := MulByte(a,b);
_if (TypeOf(a) = TypeOf(word)) and (TypeOf(b) = TypeOf(word)) then result := MulWord(a,b);
end;
i ukljucivanje makroa:
VarWord := Pomnozi(Var1Word,Var2Word);
Ovde se _if razlikuje od if. Prvo je kompajlerski if, koji odredjuje koji deo koda ce se prevoditi, a drugi je deo programa.
Ceo razvojni sistem je napravljen modularno, tako da je sintaksna analiza odvojena od generisanja koda, pa tako moze relativno lako da se napravi za bilo koji mikrokontroler.
Ako ima nekih posebnih pitanja koji zadiru u detalje, mozemo i o toma prodiskutovati.
Pozdrav.
|