Změny běhu programu

Běh programu je určován čítačem zvaným PROGRAM COUNTER. Ten ukazuje na programovou paměť a procesor v následujících strojovém cyklu vykoná pravě instrukci na kterou PC ukazuje. Běh programu však můžeme libovolně měnit a to za pomoci instrukcí pro změnu běhu programu (skoky, přeskoky,  volání)

Skoky a přeskoky

skoky a přeskoky můžeme dělit podle toho jakým způsobem pracuji. Rozlišujeme tři druhy skoků:
  • nepodmíněné skoky  (jumps)- provedení těchto skoků nezávisí na žádné podmínce, provedou se vždy
  • podmíněné skoky (branchs) - narozdíl od předchozích se provedou pouze po splnění určité podmínky
  • přeskoky (skips) - tyto speciální skoky přeskočí následující intrukci pouze tehdy, je-li splněna podmínka.
Pro dobu vykonání instrukcí skoků a přeskoků platí následující pravidlo. Je-li splněna podmínka, pak platí, že program je přerušen z normálního běhu a zpozdí se o jednu instrukci. Tedy vykonání takvého skoku trvá 2 strojové cykly. Není-li podmínka splněna, program pracuje normálně dál a tedy vykonání podmíněného skoku trvá pouze 1 instrukci. U přeskoků také záleží na následující instrukci. Pokud následující instrukce je 2 cyklová,  bude zpoždění ještě větší.

Příkládám odkaz na dokument výrobce vysvětlující význam instrukcí. My si je rozebereme podrobněji dále v tomto díle. Než se do toho pustíme, musíme si vysvětlit, jakou úlohu má v procesorech AVR registr SREG.

SREG - STATUS REGISTER

STATUS REGISTER, neboli stavový registr, je jednim z nejdůležitějších registrů procesoru AVR. Především uchovává informace o výsledcích aritmetických, ale i jiných operací (instrukcí).

I T H S V N Z C

C - příznak přetečení (carry)
  • indikuje příznak přetečení po jakékoliv matematické operaci (aitmetická, logická)
Z - nulový výsledek (zero flag)
  • nastaví se v případě, že výsledek přechozí operace byl 0
N - příznak záporného výsledku (negative)
  • je nastaven v případě že výsledek matematické operace byl záporný
V - přeplnění čísla v druhém doplňku
  • určeno pro výpočet druhého doplňku
S - znaménko druhého doplňku (sign)
  • znaménko čísla v druhém doplňku (S = N XOR V)
H - příznak přetečení nezi nibly (half carry)
  • nastaven v případě, že dojde k přetečení mezi nižší a vyšší polovinou výsledku
T - Transfer bit
  • používá se pro kopírování bitu
I- Interrupt enable
  • globální povolení / zakázání přerušení.

Zásobník

Velmi důležitou součástí každého mikroprocesoru je tzv. zásobník, jde o vyhražené misto v RAM, kam se ukládají uživatelská data, nebo návratové adresy (obsah čítače instrukcí). Zásobník je součástí  RAM a proto musí být na začátku programu korektně nastaven, aby se co nejvýše změnila nepravděpodobnost jeho přepsání, které by mohlo mít fatální následky.

Zásobník má dvě důležité funkce. Lze do něj uložit dočasně obsahy registrů například při obsluze přerušení, nebo nečekaných voláních. Druhou ale důležitější funkcí je ukládání návratových adres. Když je zavolán podprogram, uloží se do zásobníku aktuální hodnota programového čítače, tedy místo, kde se program aktuálně nachází. Po skončení podprogramu se hodnota ze zásobníku vyjme a běh programu se vrátí zpět na původní místo.

K zásobníku neodmyslitelně patří ukazatel zásobníku (STACK POINTER), jehož obsah přesně určuje, kde v RAM se zásobník nachází. Protože s každým uložením se jeho hodnota snižuje, respktive zvyšuje s každým vyjmutím, je nutné ho na začátku programu nastavit na konec RAM, to se dělá například takto.


LDI   R1, LOW (RAMEND)
OUT SPL, R1

LDI   R1, HIGH(RAMEND)
OUT SPH, R1

RAMEND je konstanta, která je specifická pro každý typ procesoru a je v ní obsaženo číslo udávající velikost RAM. Z příkladu vyplývá, že ukazatel zásobníku je doubajtové číslo, rozdělené na nižší a vyšší bajt.

Instrukce pro změnu běhu programu

SKOKY
  • RJMP - nepodmíněný skok
  • IJMP - nepodmíněný absolutní nepřímý skok
  • BRBS - provede relativní skok, je-li bit s v registru SREG nastaven
    • BRBS    s, rel
  • BRBC - totéž, ale skok se provede když je bit vynulován
  • BREQ - provede skok, je-li Z bit ve status registru nastaven - shoda při matematické operaci
  • BRNE - opačný případ k předchozímu, využití i při porovnáváni výsledku s nulou
  • BRCS - provede relativní skok, je-li C (carry) nastaveno
  • BRCC - opačné k předchozímu
  • BRLO - provede skok, je-li 1. operand menší než druhý
  • BRMI - provede skok, je-li výsledek záporný
  • BRPL - provede skok, je-li výsledek kladný

Toto je výčet nejčastěji používaných instrukcí skoků (alespoň v mém případě tomu tak je), ostatní si můžete nalézt ve výše uvedeném dokumentu. Není-li uvedeno jinak, je za instrukcí pouze návěstí.


PŘESKOKY
  • CPSE - provede přeskok v případě rovnosti operandů
    • CPSE   Rd,Rr
  • SBRC - přeskočí v případě nulového bitu v registru
    • SBRC   Rr,b
  • SBRS - opačně k předchozímu
  • SBIC  - přeskočí, je-li vynulován bit b na portu
    • SBIC   P,b
  • SBIS - opačně k předchozímu

 

Volání

Volání používáme k volání podprogramů, tzn. části programů, které využívame často a bylo by zbytečné je zapisovat několikrát stejně. Podprogramy se volají pomocí instrukcí RCALL, což je relativní volání, ICALL - nepřímé volání a navrátit se zpět mlžeme pomocí instrukce RET (return), v případě přerušení instrukcí RETI (return from interrupt).

Využití

Využití probrané látky si ukážeme na jednoduchém příkladě. Tento příklad můžete najít v knize od Davida Matouška. Jedná se o běžící světlo. Připojte na port D LED proti napájení a uvidíte sami. Doporučuji tento příklad prokrokovat v AVR Studiu.

      .NOLIST
   
 
.INCLUDE "m16def.inc"
   
 
.LIST                        

      .CSEG
     
.DEF   REG=R16
     
.EQU   DDR=DDRC
   
 
.EQU   PORT=PORTC
   
 
LDI    REG,$FF
   
 
OUT    DDR,REG
   
 
LDI    REG,LOW(RAMEND)
     
OUT    SPL,REG
   
 
LDI    REG,HIGH(RAMEND)
     
OUT    SPH,REG
     
CLC
      LDI    REG,$FF   

SMYCKA:    

      OUT    PORT,REG
   
 
RCALL  CEKEJ
   
 
ROL    REG
     
RJMP   SMYCKA

;čekací rutina (čeká asi 0,5 s)

CEKEJ:
     
LDI    R17,40
   
 
LDI    R18,0
   
 
LDI    R19,0
CEKEJA:
     
DEC    R19
     
BRNE   CEKEJA
   
 
DEC    R18
   
 
BRNE   CEKEJA
   
 
DEC    R17
   
 
BRNE   CEKEJA
     
RET




Komentovat článek

Jméno:  
Zpráva:

Komentáře k článku

Ondřej Karas - 23.8.2007 16:40

Ještě by mě zajímalo, co technikovi vadí na tomto webu tolik, že se do něj opírá při každý přiležitosti... Komu se tu nelíbí, chodit nemusí...

Ondřej Karas - 23.8.2007 06:45

Bohužel diskusní fórum bude z tohoto důvodu zrušeno.

Technik - 22.8.2007 20:35

Opravdu pěkná práce. Jen co je pravda. A mohou mi páni tvůrci tohoto webu laskavě vysvětlit, proč je v diskusním fóru míto rad, návodů a řešení debilní porno? Živíte se snad jím?

Ondřej Karas - 19.8.2007 20:28

Díky, není to jen moje práce, dělali sme na tom ve dvou. Zatím je to nedistribuovatelný, protože je to dělaný víceméně na míru tomuhle webu. Uvažovali sme o tom, že bysme to nějak uvolnili k šíření, ale nebyl čas a stále není. Pokud máš ale nějaký dotaz, rádi zodpovíme. Mužeš psát na redakce@kvetakov.net

Ondra - 19.8.2007 17:06

Pěkná práce, vidím, že s grafikou a PHP to umíš. Pod jakou licencí je ten systém? Pokud je to něco GPL kompatibilní, tak bych to rád někde stáhnul.

Ondřej Karas - 28.7.2007 13:15

To Technik: Díky za připomínku, ale každému asi dojde, že program vykoná až následující instukci... To Ondra: Máme vlastní redakční systém... Dalo to sice trochu práce, ale zas víme, kam šáhnout, když je třeba něco upravit

Ondra - 13.7.2007 17:25

Jaký používáš redakční systém?

Technik - 11.7.2007 21:31

1) Žádná instrukce, která obsahuje 8 bitovou konstantu (např. LDI, CPI, SUBI, ANDI,...), nemůže pracovat s registry R0 až R15. Takže zápis LDI R1, LOW (RAMEND) bude generovat chybu! 2) RAMEND neurčuje velikost paměti RAM, ale poslední adresu v RAM. Velikost je určena v SRAM_SIZE. 3) "Když je zavolán podprogram, uloží se do zásobníku aktuální hodnota programového čítače, tedy místo, kde se program aktuálně nachází. Po skončení podprogramu se hodnota ze zásobníku vyjme a běh programu se vrátí zpět na původní místo." A na původním místě je volání onoho podprogramu, takže se program zacyklí! Takhle ten zásobník asi nefunguje.

Ondřej Karas - 10.7.2007 16:59

Díky, opraveno

Mirek - 16.6.2007 12:08

SREG nazev bitu I je spatne, popis je jiz spravne.