UNIVERZITA TOMÁŠE BATI VE ZLÍNĚ FAKULTA APLIKOVANÉ INFORMATIKY PROGRAMOVÁNÍ MIKROPOČÍTAČŮ CVIČENÍ 2 Větvení programu, pole a cyklus v jazyce symbolických adres Jan Dolinay Petr Dostálek Zlín 2013 Tento studijní materiál vznikl za finanční podpory Evropského sociálního fondu (ESF) a rozpočtu České republiky v rámci řešení projektu: MODERNIZACE VÝUKOVÝCH MATERIÁLŮ A DIDAKTICKÝCH METOD
2 Cvičení 2 Větvení programu, pole a cyklus v jazyce symbolických adres STRUČNÝ OBSAH CVIČENÍ: Princip větvení programu a jeho realizace v assembleru Příklad na větvení programu porovnání dvou čísel Princip práce s polem v assembleru indexová adresace Příklad na práci s polem nulování pole VSTUPNÍ ZNALOSTI: Toto cvičení předpokládá znalosti získané na předchozím cvičení. CÍL: V tomto cvičení se naučíme pracovat s poli proměnných s využitím indexového adresování. Dále se seznámíme s posledním základním stavebním blokem programu (vedle iterace, větvení a cyklu probraných dříve) a to s podprogramem. Dozvíme se, jaké má použití podprogramů výhody a naučíme se je používat v našich programech. Také si ukážeme možnosti využití zásobníku při psaní programů. Cvičení se vztahuje k těmto otázkám Instrukce a formáty instrukcí. Instrukční soubor a jeho rozdělení. Příklady instrukcí z jednotlivých skupin
3 1. Řešené příklady Program 1 Porovnání dvou čísel Úkol: Máme definována čísla c1 a c2. Do proměnné vetsi má náš program uložit větší z těchto dvou čísel. Řešení Algoritmus řešení bychom slovně mohli zapsat takto: Porovnej čísla c1 a c2 Jestliže je c1 větší než c2, zapiš do proměnné vetsi obsah proměnné c1 V opačném případě ulož do vetsi obsah proměnné c2. Vývojový diagram je na následujícím obrázku. Uvedeny jsou i příslušné instrukce. Vysvětlení instrukcí je uvedeno níže. Obr. 1 Vývojový diagram řešení úkolu Jak je vidět z vývojového diagramu, porovnáváme jestli c1 je větší než c2. Jestliže je c1 větší, pokračujeme větví ANO, tedy do proměnné vetsi uložíme číslo c1 (chceme aby v této
4 proměnné bylo větší z obou čísel). Jestliže není podmínka splněna (c1 není větší než c2), pokračuje program větví NE a do proměnné vetsi se uloží c2. Potřebné instrukce Toto je seznam instrukcí, které budeme potřebovat pro řešení zadaného úkolu. Vyhledali jsme je v dokumentaci k mikropočítači, v tabulce obsahující instrukční sadu procesoru. LDA nahraje číslo uložené v paměti do registru A: A <- (M) CMP porovná obsah A s paměťovou buňkou: (A) (M) BHI skočí na zadané návěští, pokud číslo v akumulátoru A je větší než číslo v paměťové buňce M. Skok pokud (C) (Z) = 0 STA uloží obsah A do paměti. M <- (A) BRA skočí vždy (bez podmínky) na zadané návěští Direktiva: DS.B rezervuje N bajtů paměti (lze použít místo RMB) Vysvětlení programu Stěžejní je zde instrukce pro porovnání, CMP. U HC08 tato instrukce porovnává obsah registru A s obsahem zadané paměťové buňky. Před použitím této instrukce tedy musíme do registru A nahrát první z čísel, které potřebujeme porovnat. K tomu použijeme instrukci LDA, kterou již známe z minulé lekce. Po instrukci CMP pak můžeme použít některý z podmíněných skoků pro rozvětvení programu. V našem případě je použit skok BHI (skoč jestliže je větší). Skok se provede tehdy, jestliže číslo v akumulátoru A bude větší než porovnávané číslo v paměti. My do akumulátoru A nahráváme c1. Jestliže se tedy skok provede, znamená to, že c1 je větší než c2. V tom případě se tedy skočí na návěští Skok a provede se instrukce STA vetsi. Tím se uloží c1 (které je stále nahráno v akumulátoru A) do proměnné větší. Pokud se skok neprovede, bude program pokračovat instrukcí následující za BHI, (větev NE ve vývojovém diagramu) a v tom případě máme uložit do vetsi číslo c2. Protože nemáme k dispozici instrukci, která by přímo přesunula obsah jedné paměťové buňky do jiné, provedeme přesun s pomocí akumulátoru A. Nejprve nahrajeme c2 do A (instrukcí LDA), a potom uložíme obsah A (instrukcí STA) do proměnné vetsi. Poté následuje instrukce BRA, s jejíž pomocí přeskočíme instrukci STA prováděnou ve větvi ANO a skočíme přímo na konec programu.
5 Vytvoření a testování programu Kompletní výpis programu včetně automaticky generovaného kódu je na obr. 2.7. Do proměnné c1 a C2 ukládáme libovolně zvolená čísla stejně jako v minulé lekci, tak abychom program mohli otestovat. V uvedeném příkladě je do c1 uloženo číslo 3 a do c2 číslo 5. Vytvořte v prostředí CodeWarrior nový projekt stejným způsobem jak je popsáno v předchozí kapitole a zapište do kostry programu vygenerované průvodcem kód podle tohoto výpisu. Poté program přeložte a spusťte v simulátoru. Možná jste si už všimli, že místo použití tlačítka Build a Debug můžete použít přímo tlačítko Debug a pokud program ještě nebyl přeložen, vývojové prostředí jej automaticky přeloží. Pokud program neobsahuje chyby, nic se nestane. Pokud ale váš program obsahuje chyby, objeví se okno s jejich seznamem. Řádky, kde máte chybu, budou zvýrazněny a chyba upřesněna. Pokud porozumíte anglickému hlášení překladače, výrazně vám to hledání chyby usnadní, takže rozhodně doporučujeme číst hlášení překladače a nesnažit se hledat chyby naslepo porovnáváním celého programu se vzorovým kódem. Nejčastější chyby: o názvy proměnných (c1, c2 a vetsi) nezačínají od levého okraje stránky, tj. je před nimi mezera nebo několik mezer, což není dovoleno. o chybí tečka v direktivě DS-tečka-B (DS.B) o nedodrženo použití velkých/malých písmen v názvu návěští, např. u instrukce BHI je napsáno skok (malým písmem), ale návěští níže je napsáno jako Skok tj. první písmeno velké. Překladač rozlišuje velká a malá písmena v názvech návěští a proměnných. o Neuvedeno návěští, např. Konec: není v programu napsán a instrukce BRA Konec pak nemá cíl, neví kam skočit. V simulátoru vyzkoušejte, že po skončení programu bude skutečně v proměnné vetsi uloženo větší z čísel uložených v c1 a c2. Také sledujte, jak se mění stav příznakového registru procesoru při porovnání (vykonání instrukce CMP). Skok BHI se provede nebo neprovede právě podle příznakového registru, konkrétně podle příznaků (Z) a (C), viz instrukční sada a vysvětlení principů větvení na začátku této kapitoly.
6 Obr. 2 Zdrojový kód příkladu na větvení programu Obr. 3 Ladění programu
7 Změna hodnot proměnných v simulátoru Při testování tohoto programu si také vyzkoušejte možnost měnit obsah paměti mikropočítače během ladění programu: Poklepejte na hodnotu proměnné v okně Data simulátoru. Zapište novou hodnotu a stiskněte klávesu Enter. Tímto způsobem můžeme testovat chování programu s různými hodnotami proměnných c1 a c2 aniž bychom museli měnit zdrojový kód. Nemusíme ani program znovu spouštět. Po proběhnutí programu místo zavření okna simulátoru klepněte na tlačítko Reset target, tím se program restartuje. Příklad 2 Nulování pole Úkol Definujte pole M o velikosti 5 byte. Vynulujte prvky tohoto pole. Řešení Máme definovat pole M o pěti prvcích a toto pole vynulovat. Pro nulování použijeme instrukci CLR, která nuluje obsah paměťové buňky na zadané adrese. Postup bude takový, že budeme opakovat instrukci CLR v cyklu a s použitím indexového adresování postupně nulovat prvky pole M. Vývojový diagram i odpovídající kód jsou na následujícím obrázku.
8 Obr. 4 Program nulování pole Potřebné instrukce CLR vynulování bajtu paměti (na adrese, který je uvedena jako parametr instrukce). AIX - zvětšení obsahu index registru (H:X) o jedna. Vysvětlení kódu Nejprve nahrajeme do index registru adresu pole M. Pak se inicializuje počitadlo v registru A - abychom mohli cyklus ukončit po vynulování všech pěti prvků, musíme vědět, kolikrát už se provedl proto v registru A budeme uchovávat počet průchodů cyklem. Na začátku do registru A nahrajeme nulu a pak při každém průchodu smyčkou jeho obsah zvětšíme o jedna. Blok vývojové diagramu nazvaný zpracuj aktuální prvek je v tomto případě jen instrukce CLR,X, která vynuluje aktuální prvek pole. Instrukce AIX #1 pak zvětší obsah index registru o jedna a tím se posuneme na další prvek pole. INCA inkrementuje počitadlo v registru A. Poté se porovná obsah registru A s číslem 5 a jestliže je v registru A číslo menší než 5 (to znamená, že cyklus se ještě nezopakoval pětkrát), skokem na návěští opakuj se vracíme na začátek cyklu.
9 Testování programu Po přeložení a spuštění programu jej zkuste odkrokovat a sledujte nejprve v simulátoru v okně Data jak se pole M plní nulami. Poté simulátor zavřete a znovu spusťte (nebo restartujte) a sledujte tentokrát v okně Register obsah registru A, tj. počitadla cyklů. Na začátku programu zde bude nula. Při každém průchodu cyklem, při vykonání instrukce INCA se obsah registru A zvětší o jedničku. Jakmile dosáhne hodnoty 5, neprovede se už skok BLO a cyklus skončí. Nakonec spusťte program ještě jednou a všimněte si, že jak se při každém průchodu smyčkou nuluje další prvek pole M v okně Data, objevují se nuly také v okně Memory. Co to znamená? Okna Data a Memory jsou pouze dva pohledy na jednu a tutéž věc na paměť mikropočítače. Okno Memory zobrazuje přímo syrový obsah paměti mikropočítače, Okno Data pak zobrazuje logický pohled na paměť, tj. že je tam uloženo pole M o pěti prvcích. V okně Memory si všimněte levého sloupce, který začíná hodnotou 0080. To je adresa zobrazené části paměti. Každé dvojčíslí napravo od adresy pak představuje jeden bajt paměti (zobrazený v hexadecimální soustavě). První dvojčíslí je tedy obsah bajtu paměti na adrese $80, druhé je bajt na adrese $81 atd. až po $87. Bajt na adrese $88 je pak už na dalším řádku. V okně Memory můžeme tedy sledovat co se děje přímo v paměti mikropočítače. Všimněte si také při krokování programu jak funguje indexové adresování: Na začátku programu uvidíte v registru H:X (v okně Register) hodnotu 80. To je adresa, na které je umístěno pole M. Zda je tato hodnota 80, nebo 81 nebo třeba 100 není podstatné. O umístění dat do paměti rozhoduje vývojové prostředí (resp. překladač) a my nemáme zatím žádný důvod toto umístění měnit. Důležité je pouze uvědomit si, že v tomto případě pole M začíná na adrese $80. Proto na začátku programu po instrukci LDHX #M je v registru H:X číslo 80 adresa začátku pole. Instrukce CLR,X maže paměťovou buňku, která je na adrese uložené je v registru H:X. V prvním průchodu smyčkou je v H:X číslo 80, a proto CLR,X smaže bajt paměti na adrese $80. Po inkrementaci registru (instrukcí AIX #1) je v H:X číslo 81 a všimněte si, že po provedení instrukce CLR,X se vynuluje bajt paměti na adrese 81. (úplně stejně jako bychom si představili, že místo CLR,X je zde zapsána instrukce CLR $81). A tak to pokračuje pro další prvky pole. Na obrázku 5 je situace po provedení CLR s obsahem H:X = $82. V okně Memory vidíte, že bajt na adrese $82 byl právě vynulován červeně simulátor zvýrazňuje hodnotu změněnou v právě provedeném kroku.
10 Příklady k procvičení Obr. 5 Ladění programu Nulování pole. 1. Upravte program z příkladu č. 1 (porovnání 2 čísel) tak, aby vyhledal minimální hodnotu a uložil ji do proměnné cmin. 2. Definujte tři proměnné c1, c2 a c3, každou o velikosti 1 byte a uložte do nich hodnoty podle uvážení. Vytvořte program, který v nich nalezne maximální číselnou hodnotu a uloží ji do proměnné cmax. Předtím než začnete vytvářet program, zakreslete vývojový diagram představující algoritmus řešící daný úkol. 3. Vytvořte program, který v 5-ti prvkovém poli data o velikosti každého prvku 1 byte vyhledá maximální prvek a uloží jej do proměnné dmax. Předtím, než začnete vytvářet program, nakreslete na papír vývojový diagram představující algoritmus řešící daný úkol. 4. Modifikujte program podle bodu 4 tak, aby vyhledával minimální prvek pole. Pro jeho uložení zvolte proměnnou dmin Doplňující zdroje [1] Freescale: Firemní dokumentace pro mikropočítače HCS08, dostupné online: http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=s08gb&nodeid= 01624684491437EDD5