Produkty Novinky Články Návody Kontakty

Zásobník a podprogramy

Procesor má plně sestupný zásobník, ukazatel vrcholu zásobníku SP obsahuje adresu poslední uložené položky. Při provádění instrukce PUSH, procesor nejdříve odečte hodnotu čtyři od obsahu ukazatele vrcholu zásobníku a následně na tuto adresu uloží požadovanou hodnotu. Vyjmutí hodnoty ze zásobníku, které provádí instrukce POP, má opačný průběh. Procesor z adresy vrcholu zásobníku přečte uloženou hodnotu a následně k vrcholu zásobníku přičte hodnotu čtyři.
Na zásobník se vždy ukládá celé 32-bitové slovo, adresy ukazující na zásobník musí být beze zbytku dělitelné čtyřmi, jejich dva nejnižší bity jsou vždy nulové. Hodnota bitu CONTROL[1] určuje, který ze zásobníků, MSP nebo PSP, je při PUSH a POP instrukcích použit.
​
PUSH    {R0}    @ R13 = R13 - 4, mem[R13] = R0
POP     {R0}    @ R0 = mem[R13], R13 = R13 + 4
​
Stejně tak, při použití názvu registru R13 nebo SP, instrukce pracují buď s hlavním zásobníkem MSP nebo zásobníkem procesu PSP. To platí samozřejmě pouze pro kód v provozním režimu vlákna. V režimu handleru se vždy pracuje s hlavním zásobníkem MSP. Přímý přístup k registrům MSP a PSP umožňují speciální instrukce MSR a MRS.
Jednoduché aplikace většinou používají pouze hlavní zásobník MSP, není nutné, aby přepínaly mezi oběma zásobníky. Pro složitější systémy může být vhodnější použít oba zásobníky, například aby chybná aplikace nemohla porušit obsah zásobníku jádra systému.
​
@ pokud CONTROL[1] = 0 
MOV     R0, R13         @ R0 = MSP 
MOV     SP, R1          @ MSP = R1 
MRS     R0, MSP         @ R0 = MSP 
MSR     PSP, R1         @ PSP = R1 
PUSH    {R0}            @ MSP = MSP - 4, mem[MSP] = R0
        
@ pokud CONTROL[1] = 1 
MOV     R0, R13         @ R0 = PSP 
MOV     SP, R1          @ PSP = R1 
MRS     R0, MSP         @ R0 = MSP 
MSR     PSP, R1         @ PSP = R1 
PUSH    {R0}            @ PSP = PSP - 4, mem[PSP] = R0 
​
Instrukce PUSH a POP mohou pracovat i s více registry najednou. Ve složených závorkách argumentu instrukce může být seznam registrů oddělených čárkou, případně i rozsah registrů. To se používá třeba při volání podprogramu pro uchování obsahu registrů a jejich obnovení.
​
@ hlavní program
main:
        ...
        @ volání podprogramu subr
        BL      subr                    @ PC = subr
        ...                             @ LR = adresa následující instrukce
​
@ podprogram subr
subr:
        PUSH    {R0-R7, R12, R14}       @ uschovej registry R0-R7, R12, R14
        ...
        POP     {R0-R7, R12, R14}       @ obnov registry R0-R7, R12, R14
        BX      LR                      @ návrat z podprogramu
​
Pro uložení adresy návratu při volání podprogramu je vyhrazen registr R14 - LR - Link register. Instrukce BL (Branch with Link) uloží do LR adresu následující instrukce (t.j. adresu návratu) s nejméně významným bitem (bit[0]) nastaveným na hodnotu 1 a do registru R15 - PC - Program counter adresu podprogramu.
Návrat z podprogramu provede instrukce BX (Branch and Exchange). Jejím operandem je název registru, který obsahuje cílovou adresu skoku. Nejméně významný bit této adresy musí mít hodnotu 1. Skok je ale proveden na adresu s nulovou hodnotou bitu[0]. Tento bit určuje, zda má být procesor instrukcí BX přepnut do stavu Thumb (bit[0] = 1) nebo do stavu ARM (bit[0] = 0). Pokud by měl tento bit nulovou hodnotu, pokusí se instrukce BX o přepnutí procesoru do stavu ARM, což vyvolá chybovou výjimku, protože Cortex-M3 pracuje pouze ve stavu Thumb.
Skok na adresu může být vyvolán také zápisem adresy do registru R15, který je vyhrazen jako čítač instrukcí PC - Program counter.
​
MOV     R0, #0x801
MOV     PC, R0          @ skok na adresu 0x800
​
Stejně jako v předchozím odstavci platí, že hodnota zapsaná do registru PC musí mít nastavený nejméně významný bit na jedničku, jinak dojde k pokusu o přepnutí do stavu ARM a tím k vygenerování chybové výjimky.
Pokud aplikace pracuje s jedním zásobníkem, je vhodné jako adresu vrcholu zásobníku použít nejvyšší adresu oblasti interní SRAM zvýšenou o jedničku. Jak jsme si již dříve řekli, před uložením položky na zásobník se nejdříve sníží obsah SP o 4. Tím dostaneme adresu posledního 32-bitového slova v interní SRAM a to je adresa, na kterou bude uložena první položka zásobníku. Pokud jako příklad vezmeme mikrokontrolér, který obsahuje 8 KB statické RAM, adresy oblasti SRAM jsou od 0x20000000 do 0x20001FFF. Iniciační hodnota pro registr SP, která bude uložena na adrese 0x00000000 je 0x20002000.