Každý program musí být schopen přesunů dat a to mezi registry, registry a pamětí, registry a vstupy/výstupy. Při této operaci si musíme vždy uvědomit, kolikabitové číslo přesouváme. Počet bitů je většinou specifikován jménem použitého registru (osmibitové - AH, AL, BH, BL, . . ., šestnáctibitové - AX, BX, BP, DI, ES, DS . . .). V případě, že používáme jen paměť, specifikuje počet bitů pro operaci označení:
Všechny přesuny tohoto typu provedeme univerzální instrukcí:
Použití této instrukce demonstruje příklad:
uses crt;
var slovo:word; {v paměti rezervuj 16 bitů a označ je
slovo}
slabika:byte;{v paměti rezervuj 8 bitů a označ je
slabika}
begin
asm
MOV
AL,10
{do registru AL dosaď 8 bitů, hodnotu 10}
MOV
slabika,AL
{do paměti na místo ozn. slabika dosaď obsah AL}
MOV
BX,10
{do registru BX (16 bitový) dosaď 10}
MOV
slovo, BX
{do paměti na místo ozn. slovo dosaď 16 bitů BX}
end;
writeln (slabika,' ',slovo);
readkey;
end.
Tento program má po překladu na místech proměnných v bloku asm označení paměťového místa, které pro ně bylo vyčleněno. Místo pro proměnné je vždy v segmentu globálních proměnných. Segmentová adresa tohoto bloku je vždy umístěna v registru DS. To, že DS ukazuje na segment dat programu, může vést k chybě, která spočívá v jeho změně a následném čtení z globálních proměnných. Takže pozor! Po změně registru DS je práce s globálními proměnnými nemožná, protože jsme si k nim uřízli cestu. Do segmentových registrů nejde dosadit hodnota přímo. Tu nejrychleji dosadíme tak, že ji vložíme do některého univerzáního registru a z něj teprve do segmentového registru (například MOV AX,adresa; MOV ES,AX).
Místo (offset) v paměti označuje vždy určitá hodnota zapsaná v hranatých závorkách. Instrukce MOV BYTE PTR ES:[$100F], 10 znamená: na adresu slabiky offset 100F ($ označuje použití hexadecimální soustavy) v segmentu určeném adresou v ES, dosaď hodnotu 10. Jestliže segment nespecifikujeme označením a dvojtečkou, vztahuje se adresa k segmentu v DS. V praxi by tato metoda omezovala programátora v rozletu. Proto ASM86 umožňuje i další metody adresace. Ale popořadě . . .
Jejich použití umožní zjistit adresu proměnných deklarovaných v části var (const . . .).
Příklad:
var promenna: byte;
begin
asm
MOV
BYTE
PTR
[offset
promenna], 10 {na adresu slabiky proměnné dosaď 10}
end;
end.
Segmentová adresa se v tomto příkladu nemusí určit. Je v DS, a ten se nemusí uvádět. Překladač Pascalu tuto metodu používá i pro naše globální proměnné. Při překladu je totiž každé proměnné přiděleno místo v paměti s pevnou offsetovou adresou (takže zápis OFFSET proměnná nese právě tuto adresu). Specifikace, jestli se jedná o slabiku, nebo slovo, je nutná, protože jinak by procesor nevěděl, jestli má číslem obsadit jednu, nebo dvě slabiky.
var promenna: byte;
begin
asm
MOV
BX,
offset promenna {do BX dosaď adresu proměnné}
MOV
BYTE
PTR
[BX], 10
{na její adresu dosaď hodnotu 10}
end;
end.
var pole: array [0..9] of byte;
begin
asm
MOV
SI, 0
{nuluj
registr SI}
MOV
BYTE
PTR
offset
pole[SI], 10{adr. pole sečti s SI a dosaď 10}
end;
end.
Program dosadí na první místo pole hodnotu. Protože registr SI můžeme zvyšovat, budeme tímto způsobem realizovat pohyb v poli.
var pole: array [0..9] of byte;
begin
asm
MOV
BX,
offset pole {do registru BX dosaď adresu
pole}
MOV
SI, 0
{do registru SI dosaď 0}
MOV
BYTE
PTR
[BX][SI],
10 {na první prvek v poli ulož 10}
end;
end.
V assembleru mikroprocesoru 8086 se objevuje i nový výraz. Prefix znamená určitou specifikaci pro následující instrukci. Zatím jsme si ukázali, jak změnit specifikaci segmentového registru adresy s pomocí jeho označení a dvojtečky. Dalším způsobem je použití prefixu změny segmentu: SEGDS, SEGES, SEGCS, SEGSS. Tato označení jsou prefixy přeskočení (změny segmentu) pro jednotlivé segmentové registry. Například: MOV AX, ES:[BX] je stejné, jako bychom použili SEGES MOV AX, [BX] (i když zápis je různý, kód programu bude po překladu stejný).
Zásobník je část v paměti počítače vyhrazená k odkládání dat. Je organizovaná tak, že data, která jsou uložena naposledy, vyjímáme jako první. Na vrchol zásobníku ukazují adresy uložené v registrech SS a SP (případně BP). Přidáváním dat do zásobníku se offset v SP automaticky snižuje o dvě (a naopak). Musíme si tedy uvědomit, že do zásobníku můžeme odkládat jen šestnáctibitová data. Pro práci se zásobníkem slouží instrukce:
Příklad:
var promenna:word;
begin
promenna:=10; {do paměti na adresu proměnné dosaď
10}
asm
MOV
AX, promenna
{obsah proměnné dosaď do registru AX}
MOV
BX,$BBBB
{do regisru BX dosaď číslo}
PUSH
AX
{ulož obsah AX}
PUSH
BX
{ulož obsah BX}
MOV
AX,$AAAA
{přepiš obsah AX}
MOV
BX,$CCCC
{přepiš obsah BX}
POP
BX
{obnov obsah BX}
POP
AX
{obnov obsah AX}
MOV
promenna, AX
{vrať obsah AX do proměnné}
end;
end.
Tento program naznačuje postup ukládání a vybírání dat do a ze zásobníku. V zásobníku jsou uloženy i lokální proměnné procedur a funkcí. Jsou zde i parametry, kterými je podprogram volaný. (Proto lokální proměnné NEMAJÍ segmentovou adresu v DS.) Občas potřebuje programátor uložit registr příznaků F, aby ho později mohl obnovit do původního stavu. K tomu požíváme instrukci PUSHF (pro uložení) a POPF (pro obnovení). Jestliže ve vkládaném assembleru chceme měnit některý ze "zakázaných" registrů (DS, BP), můžeme si jeho obsah uložit do zásobníku. Podmínkou je ale to, že nezměníme registry SS, SP. Tím bychom si podřízli větev pod sebou. Další možné použití zásobníku je při práci s částí pamětí, ve které máme pole slov (šestnáctibitových dat). Nasměrováním vrcholu zásobníku (SS:SP) na konec tohoto pole můžeme instrukcemi PUSH a POP s tímto polem pracovat. Přitom se bude automaticky zvyšovat a snižovat adresa. Pozor ale, obsahy SS a SP je nutné zase uschovat, nejlépe do paměti na místa proměnných. V tom případě ale nemůžeme měnit registr DS (ES).
Každý se někdy pokusíme zapsat na port a číst z něj. Je dobré si uvědomit, že můžeme zapisovat osm i šestnáct bitů. Každý port, stejně jako slabika v paměti, má svojí adresu. Při zápisu šestnácti bitů zapisujeme tedy i na port s adresou o jednu vyšší. Práci s porty provedeme instrukcemi:
Data se čtou, nebo zapisují z (do) registru AL (osmibitový přístup), AX (šestnáctibitový přístup). Adresu portu specifikuje buď přímo adresa (IN AL, $0F) při adrese osmibitové (spodních 256 portů), nebo registr DX, ve kterém je šestnáctibitová adresa (MOV DX, $F10; OUT DX, AL).
Mezi přesuny dat patří i: