;********************************************************************
$MOD51
$TITLE(BYTE SIGNED MULTIPLY)
$PAGEWIDTH(132) ;HLAVICKA
$DEBUG
$OBJECT
$NOPAGING
;********************************************************************
ORG 0
MOV P1,#0FFH ;aktivace portu pro cteni vst. hodnot
MOV A,#080H
ACALL displej
smyc1: JNB P1.0,jedna ;testuj stavy mikrospinacu a pri
JNB P1.1,zpatecka ;aktivite posli cislo na displej
JNB P1.2,neutral
JNB P1.3,pet
JNB P1.4,ctyri
JNB P1.5,tri
JNB P1.6,dva
SJMP smyc1
jedna: MOV A,#6H ;reprezentave cisla 1
ACALL displej
SJMP smyc1
dva: MOV A,#05BH ;reprezentave cisla 2
ACALL displej
SJMP smyc1
tri: MOV A,#04FH ;reprezentave cisla 3
ACALL displej
SJMP smyc1
ctyri: MOV A,#66H ;reprezentave cisla 4
ACALL displej
SJMP smyc1
pet: MOV A,#06DH ;reprezentave cisla 5
ACALL displej
SJMP smyc1
neutral:MOV A,#40H ;reprezentave pomlcky
ACALL displej
SJMP smyc1
zpatecka:MOV A,#39H ;reprezentave znaku C
ACALL displej
SJMP smyc1
;********************************************************************
displej:CPL A ;provede negaci a posle ven
MOV P2,A
RET
END
;********************************************************************
|
Na začátku je jako vždy nejprve hlavička zdrojového souboru. Direktivou ORG0 nastavíme počáteční adresu programu na adresu 0. Nyní zápisem hodnoty 0FFH zapíšeme do výstupního registru portu P1 jedničky, tím jej nastavíme do vstupního režimu. Nyní vložíme do Akumulátoru (již známe z minula) hodnotu 80H. Proč ? To si za chvilku povíme. Následující instrukcí je instrukce ACALL. Tuto instrukci ještě neznáme. tak se na ni podíváme podrobněji. Tato instrukce provede volání podprogramu ležícího na adrese uvedené za touto instrukcí. V praxi to znamená, že se uloží návratová adresa do zásobníku, provede se skok na podprogram, a po jeho vykonání se instrukcí RET na konci podprogramu vyzvedne návratová adresa ze zásobníku a zavede se do programového čítače (Program counter - PC). Prostě a jednoduše instrukcí RET se vrátíme z podprogramu zpět na instrukci následující za instrukcí volání podprogramu. Pro naprosté pochopení můžeme opět sáhnout po staré dobré kuchařkové analogii. V receptu máme např. rozklepněte vejce, a vložte na pánev. Takže co uděláme ? Po přečtení rozklepněte vejce "bude zavolán podprogram" který zajistí dojít do lednice, rozklepnout vejce a uklidit skořápku. Po návratu z tohoto podprogramu se bude pokračovat dalším krokem - vložte na pánev.
Protože hledání adresy, na kterou skočit je nemyslitelné, opět použijeme nám již známé návěští, kterým je libovolné slovo, pro lepší orientaci jsem zvolil slovo displej. Takže volání ACALL displej provede skok na adresu s tímto návěštím. Jestliže se podíváme na samý konec prográmku, na rutinu "displej" zjistíme, že provede následující kroky: instrukcí CPL A neguje všechny bity akumulátoru - to je nutné kvůli hardwarovému připojení displeje - aktivní jsou bity v log. L. Další instrukce (MOV P2,A) provede odeslání hodnoty na port procesoru, a v tomto okamžiku se tedy rozsvítí ty segmenty, kde je na portu log. úroveň L, naopak zůstanou zhasnuté ty, kde je log. úrpveň H. Poslední instrukcí této rutinky je RET, která zajistí návrat z tohoto podprogramu na instrukci následující za instrukci ACALL.
Ptáte se, v čem je hlavní kouzlo podprogramů ? Představte si, že místo každého volání "ACALL displej" budete muset vložit obsah této rutiny. Jsou to sice jen 2 řádky, použitím podprogramu máme ušetřeno cca 7 řádek kódu, ale vezměte si např. rutinu vícebytového dělení, která má kolem 100 řádek kódu. To je již značná úspora (času, paměti, nervů, račte doplnit další ... ), pokud místo každého vypisování rutiny pouze zapíšete ACALL, nebo LCALL s návěštím dělení. |