8. Laboratoř: Aritmetika a řídicí struktury programu Programy v JSA aritmetika, posuvy, využití příznaků Navrhněte a simulujte v AVR studiu prográmky pro 24 bitovou (32 bitovou) aritmetiku: sčítání, odčítání, aritmetický posuv vpravo, vlevo, násobení malou konstantou (2 až 5). Využijte instrukce ADD, ADC, SUB, SBB, podmíněné skoky. Pracujte s registry. Architektura mikropočítače AVR, vývojové prostředí AVR Studio Prezentace: sap-avr2.pdf Kompletní instrukční sadu (anglicky) najdete v odkazech. Viz též přehled instrukcí (česky) Bodované úlohy: Úkol 1: Spočítejte následující výraz R20 = (4 * R16 + 3 * R17 - R18) / 8 LDI R16, 5 LDI R17, 10 LDI R18, 58... doplňte instrukce... Operandy jsou 8-bitové, výsledek 8-bitový, veškeré mezivýsledky udržujte také 8- bitové. Výraz by měl být spočítán správně. Pokud nelze výraz správně spočítat (s použitím 8- bitových registrů), program by měl toto indikovat (např. nastavením V flagu). Úkol 2: Napište program, který zobrazí na displeji zadané čísloo v šestnáctkové soustavě Použijte knihovny pro práci s displejem z minulého cvičení. Použijte instrukce pro posuv a maskování, abyste dostali jednu šestnáctkovou číslici Použijte porovnání a sčítání, abyste z číslice vytvořili ASCII znak (kód A je 65, kód 0 je 48) Úkol 3: Napište program, který sečte dvě 32 bitová čísla a zobrazí na displeji informaci o správnosti výsledku čísla považujte jednak doplňkovém kódu za čísla nezáporná (bez znaménka) a jednak za čísla v
na displeji zobrazte buďď hlášku overflow (OVER), pokud došlo k přetečení v doplňkovém kódu nebo carry (CARRY) v případě, že k přetečení nedošlo, ale vypadl nejvyšší bit (signalizace, že v případě interpretace čísel jako nezáporných se výsledek nevešel do registrů) nebo nulu (0) v případě, že se nenastavil ani příznak C, ani V. Trocha teorie Jazyk symbolických instrukcí - asembler Instrukce - mnemonika, operandy Příklady: Jméno instrukce Operandy (mnemonika) add r2, r3 sts 0x123, r5 r16, 0x23 Pseudoinstrukce - direktivy Pseudoinstrukce se nepřekládají (a tedy ani nevykonávají). Pseudoinstrukcee řídí překlad - jsou to příkazy pro překladač. Příklady: Pseudoinstrukce (direktiva) Význam.cseg umístit do paměti programu (code segment).dseg umístit do paměti dat (data segment).org a pokračovat na adrese a.byte n rezervovat n bytů (pro proměnnou).db <seznam> definovat hodnotu bytů v paměti jako <seznam>, např..db 0x12, 223, 'A', baf vlevo uvedené příklady definují stejné hodnoty.db 18, 0xDF, Ab, 0x61, 0x66 Komentáře Od středníku do konce řádku Návěští add r1, r2 ;TOTO JE KOMENTÁŘ Identifikátor zakončený dvojtečkou, označuje adresu. Každé další použití ohoto identifikátoru je nahrazeno číslem odpovídajícím adrese.
navesti:... Překlad assembler -> strojový kód Jméno instrukce (mnemonika) operační znak Kódování parametrů instrukce Výpočet adres z návěští Adresace paměti dat Přímá adresace - adresaa je součástí instrukce Např. sts lds 0x123, r5 r18, 0x100 S návěštím sts lds promenna, r20 r19, promenna Nepřímá adresace - přes indexregistry X, Y, Z, instrukce ld, st o Indexregistry: X = (r27, r26) Y = (r29, r28) Z = (r31, r30) o Možnost pre-dekrementace (-X, ) a post-inkrementace (X+, ) Např. ld st r28, 0x12 r29, 0x01 ; Y = 0x0112 r1, Y ; load Y+, r5 ; store (post-increment) Příklad.dseg.org 0x100 procesor) prom1:.byte 1 prom2:.byte 2 ; pamet dat ; od adresy 0x100 (implicitni pro nas ; v pameti dat muzeme deklarovat promenne ; jednobajtova promenna ; dvoubajtova promenna.cseg.org 0 ; nasledujici umistit do pameti programu ; zaciname od adresy 0 (implicitni) jmp start.org 0x100 start: ; do promenne muzeme ulozit cislo pres registr: r16, 0x12 sts prom1, r16 ;... lds prom1, r2 ;...
ld st r28, low( (prom2) ; neprime adresovani r29, high(prom2) r1, Y ; load Y+, r5 ; store (post-increment) end: jmp end Adresace paměti programu Adresace programu v paměti programu - skoky, volání podprogramů. Přímá absolutní: jmp, call Přímá relativní: rjmp, rcall, podmíněné skoky breq, brne, Nepřímá: ijmp, icall (podle Z) Adresace dat v paměti programu (konstanty): Pozor, paměť programu je 16bitová, a každé návěští v paměti programu značí adresu šestnáctibitového slova. Chceme-li načítat data - konstanty (např. řetězce) z paměti programu, musíme spočítat adresu bajtu. Jen nepřímá adresace, lpm..cseg ; nasledujici umistit do pameti programu (implicitni).org 0 ; zaciname od adresy 0 (implicitni) jmp start.org 0x100 retez:.db "Toto je muj retezec",0 ; retezec zakonceny nulou start: ;... r30, low( (2*retez) r31, high(2*retez) ; dolni bajt bajtove adresy retezce ; horni bajt bajtove adresy retezce lpm r16, Z+ ; nahraj bajt (znak) z retezce do r16, posun pozici v retezci ;... nejaka uzitecna cinnost... lpm r16, Z+ ; nahraj dalsi bajt (znak) z retezce do r16, posun pozici v retezci ;... end: jmp end Podprogramy - instrukce "call", "ret" Volání podprogramu: call adresa Uloží na zásobník obsah registru PC (který momentálně ukazuje na první instrukci za call ) o Nejdřív nižší bajt, pak vyšší bajt Skočí na adresu podprogramu, tj. do PC nahraje adresu, která je parametrem instrukce call Návrat z podprogramu: ret
Vybere ze zásobníku adresu a uloží ji do PC - tím je proveden návrat, běh programu pokračuje na adrese za volající instrukcí call. Předávání parametrů: Přes registry - rychlé, omezený počet Na zásobníku - flexibilní, pomalejší V paměti v globální proměnné V paměti s předáním ukazatele Příklad ; podprogram s predavanim parametru a navratove hodnoty pres registry ; vypocita prumer r16 a r17, vraci v r16 prumer: add r16, r17 asr r16 ; aritmeticky posuv doprava ret... r16, 13 r17, 16 call prumer ; vrati se s r16= =14 r16, 8 r17, 12 call prumer ; vrati se s r16... Čekací smyčky V Javě/C++: for (i=0; i<120; i++) {} V asembleru AVR: cek: r20, 120 dec r20 brne cek Jiný způsob: clr r16 r17, 100 cycle: inc r16 cpse r16, r17 ; compare and skip if equal jmp cycle Dvě vnořené čekací smyčky např.: r21, 33 cek2: r20, 120
cek: dec r20 brne cek dec r21 brne cek2