Adresace dat v paměti dat
Adresa paměti dat je 16bitová, ale na rozdíl od paměti programu je organizovaná po bajtech.
V paměti dat lze rezervovat příslušný prostor a za běhu programu je přístupná pro zápis i čtení.
Adresy v rozsahu 0-0xFF jsou sdílené s registry a vstupními/výstupními zařízeními - nepoužívejte je tedy k ukládání dat.
Simulátor předpokládá, že po resetu je obsah paměti vynulovaný, ale na vývojovém kitu není paměť inicializovaná a po resetu v ní může být libovolný obsah.
Pro přístup do paměti dat lze použít následující typy adresace:
- Přímá adresace – adresa je součástí instrukce
- Instrukce sts a lds
- Možnost využít návěští
- Nepřímá adresace – přes indexregistry X, Y, Z
- Instrukce ld, st
- Indexregistry jsou 16bitové a jsou mapované na běžné r registry, aby s nimi bylo možné pracovat i běžnými instrukcemi:
- X = (r27, r26) – pouze pro paměť dat
- Y = (r29, r28) – pouze pro paměť dat
- Z = (r31, r30) – pro paměť dat i programu
- Všechny indexregistry mají možnost pre-dekrementace (-X) a post-inkrementace (X+)
Následující příklad obsahuje instrukce pro práci s pamětí dat i programu (detaily o paměti programu naleznete zde).
.dseg ; prepnuti do pameti dat
.org 0x100 ; od adresy 0x100 (adresy 0 - 0xFF nepouzivejte)
prom1: .byte 1 ; rezervovani mista pro 1 bajt 1
prom2: .byte 10 ; rezervovani mista pro 10 bajtu
;.org 0x106 ; na adrese 0x106 "bydli" prom2, prekladac hlasi konflikt
; a nedovoli vice navesti pro jednu pozici pameti 2
;prom3: .byte 1
.cseg ; prepnuti do pameti programu
; Zacatek programu - po resetu
.org 0
jmp start
.org 0x100
delka: .db 6 ; definice read-only konstanty v pameti programu (jeden bajt s hodnotou 6) 3
retez: .db "MUJ RETEZEC",0; retezec zakonceny nulou (nikoli znakem "0") 4
start:
ldi r20, 50
sts 0x100, r20 ; ulozi obsah registru do datove pameti na adresu 0x100
ldi r21, 60
sts prom1, r21 ; ulozi obsah registru do datove pameti na adresu prom1 (tj. take 0x100) 5
lds r18, 0x100 ; nacte obsah registru z datove pameti z adresy 0x100
lds r19, prom1 ; nacte obsah registru z datove pameti z adresy prom1 (tj. take 0x100)
ldi r28, 0x06
ldi r29, 0x01 ; Y = 0x106 6
st Y, r20 ; uloz r20 na adresu, kam ukazuje Y (tj. 0x106)
st Y+, r21 ; uloz r21 na adresu, kam ukazuje Y a pote inkrementuj Y
st -Y, r21 ; dekrementuj Y a pote uloz r21 na adresu, kam ukazuje Y
ld r20, Y ; nacti r20 z adresy, kam ukazuje Y 7
ldi r26, low(prom2)
ldi r27, high(prom2) ; X = 0x101
ldi r30, low(2*retez) ; 8
ldi r31, high(2*retez); Z = 0x100
lpm r16, Z+ ; 9
end: jmp end- .byte je tzv. direktiva pro překladač. Je to pokyn, aby překladač rezervoval zadaný počet bajtů v paměti (dat). Číslo 1 tedy není hodnota, která by se do paměti uložila (na rozdíl od paměti programu u <3>).
- Překladač automaticky hlídá konflikty v umístění návěštích. Výrazně tak snižuje pravděpodobnost, že si v datové paměti omylem přepíšete užitečná data.
- .db je další direktiva pro překladač. Je to pokyn, aby následující hodnoty vzal jako seznam bajtů a uložil do paměti (programu). Je možno zadat jednotlivé hodnoty bajtů oddělené čárkou, nebo i celý řetězec v uvozovkách.
- retez je návěští (ukazatel) prvního znaku řetězce (tj. "N"). Je to tedy konstanta, ze které překladač může vzít spodní bajt (low(2*retez)) a pomocí ldi ho uložit do registru r30. Obdobně horní bajt (high(2*retez)) a registr r31.
- Použití návěští namísto přímého čísla je důrazně doporučeno. Na případné překlepy může totiž upozornit překladač.
- Registr Y je namapován na registry r28 a r29. Jeden z důvodů je právě možnost načtení hodnoty přes dvě instrukce ldi, protože AVR pracuje s 8bitovými daty. AVR ale obsahuje i instrukce, které lze použít přímo s dvojicí registrů (tj. i s X, Y a Z) a to jak nahrávací/přesouvací, tak i aritmetické – viz přehled instrukcí.
- I pro ld existují varianty s inkrementací a dekrementací – viz přehled instrukcí.
- Paměť programu je organizovaná po 16bitových slovech. retez tedy obsahuje adresu 16bitového slova. Aby bylo možno pracovat s jednotlivými bajty, je adresa pro instrukci lpm násobená dvěma (detaily viz paměť programu).
- Instrukce lpm r16, Z+ nahraje jeden bajt (znak) z paměti programu, na který ukazuje Z, do registru a zároveň inkrementuje Z. Pro práci s pamětí programu lze použít pouze registr Z.