assembler
struktura procesoru
Obecnou strukturu mikroprocesoru si z hlediska vnitřní stavby můžeme představitna dvě části. Část
sběrnicovou - řadič a část prováděcí ALU
- aritmetickologická jednotka. Řadič vybírá instrukce z paměnti a ukládá je do vnitřní fronty,
ze které je čte ALU. Řadič také řídí přenos dat po sběrnicích. Obě tyto části pracují na sobě nezávisle
a tím se zvyšuje výkon procesoru. Tento optimální stav je narušen příkazem skoku, neboťť v tento okamžik
musí řadič vyprázdnit vnitřní frontu a načíst nové instrukce pro následné zpracování ALU.Další důležitou
částí jsou registry. To není nic jiného než vnitřní pamět, do kterých
je možné ukládat proměné programu, pukud by nestačil počet registrů pro proměnné, pak je možné zapisovat
data i přímo do paměti. Zvláštní kapitolou jsou speciální registry. ACC
akumulátor - u mikročipů je instrukce prováděna nad akumulátorem a oprandem, u PC (značen AX resp.
AXE) umožňuje assembler provádět instrukce nad dvěma oprandy a tento register zrácí svůj původní význam.
Register PSW - stavový register, v tento registru se předávají
informace o provedených aritmetickologických instrukcí procesoru (bude vysvětleno později).
Register DPTR slouží k adresování (k přístopu do) horní části paměti.
Na obrázku jsou registry 8 bitové a pomocí nich mohu adresovat pouze oblast paměti 0-FFh. DPTR je 16-ti
bitový registr a umožňuje adresovat oblast paměti do FFFFh. Podobně funguje i register
SP - ukazatel na zásobník. Zásobník je typ paměti LIFO (Last In First
Out) a využívá se např. pro předávání parametrů podprogramu. Register PC
je čítač instrukcí programu. Velikost paměti a registrů jsou dány konkrétním typem procesoru.
registry PC procesoru 80x86
všeobecné registry
16 bitů |
|
8 bitů |
8 bitů |
|
AX |
= |
AH |
AL |
akumulátor (acumulator) |
BX |
= |
BH |
BL |
báze (base) |
CX |
= |
CH |
CL |
čítač (counter) |
DX |
= |
DH |
DL |
data (data) |
Dnes jsou k dispozici i 32 bitové registry EAX, EBX, ECX, EDX
Indexové a ukazatelové registry
16 bitů |
|
SP |
ukazatel zásobníku (stack pointer) |
BP |
bázový ukazatel (base pointer) |
SI |
indexový register zdroj. adresy (source index) |
DI |
indexový register cílové. adresy (destination index) |
Tyto registry se nejčastěji používají pro adresaci dat
Segmentové registry
16 bitů |
|
CS |
segmentový register programu (code segment) |
DS |
segmentový register dat (data segment) |
SS |
segmentový register zásobníku (stack segment) |
ES |
pomocný segmentový register (extra segment) |
Tyto registry slouží k adresaci. Logická adresa se skládá ze dvou částí segment:offset.
Každá z těchto částí je tvořena 16 bit. slovem, proto může každý segmet adresovat 64KB paměti. Pro adresaci
1MB ale potřebujeme 20 bitů. Abychom toho dosáhli, převedeme logickou adresu na fyzickou. Segmentovou část
posuneme o 4 bity vlevo (násobíme 16) a k tomuto číslu přičteme ofset a tím vznikne 20 bitová
fyzická adresa.
Instrukční čítač
16 bitů |
|
CS |
ofsetová adresa právě prováděné instrukce |
Obsah tohoto registru nelze přímo měnit, ke změnám dochází vždy po vykonání
právě prováděné instrukce. Celá adresa je dána CS:IP
Stavový register
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| | | | OF | DF | IF | TF |
SF | ZF | | AF | | PF | | CF |
Tyto příznaky se nastaví po provedení aritmetickologické operace. Příznaky TF, IF a DF nastavuje programátor.
OF Overflow flag =1 pokud došlo k přeplnění
DF Direction flag určuje směr zpracování řetězců, je-li DF=1,
obsah registrů SI a DI se se pro provedení řetězové operace sníží(řetězec se zpracovává odzadu.
IF Interrupt Enable Flag =1 umožňuje externí přerušení
TF Trap flag =1 po každé instrukci procesor vygeneruje přerušeni
INT1. Složí pro účely ladění programu
SF Sign flag =1 pokud je výsledek záporný
ZF Zero flag =1 pokud je výsledek roven nule
AF Auxiliary flag =1 pokud došlo k přenosu z 3-tího do 4-tého bitu.
Používá se v BCD aritmetice
PF Parity flag =1 pokud dolních 8 bitů má sudý počet jedniček
CF Carry flag =1 pokud došlo přenosu z nejvyšího bitu
způsoby adresování
Přímé adresování Tento nejednodušší způsob adreace umožňuje
přímo naplnit register hodnotou, která je v paměti na offsetové adrese. Příkaz mov AX,[DATA] naplní
register AX obsahem paměťového místa označeného DATA. Data je ofsetová adresa paměti příslušného segmentu.
Segmentovou adresu máme v něktrém ze segmentových registrů
Registrové adresování Offsetovou adresu uložíme do něktrého z registrů
SI, DI,BX,BP, pak příkaz mov CX,[BP] naplní register CX obsahem paměťového místa SS:BP
Bázové relativní adresování Představme si, že příkaz mov AX,[BP] neukazu
v paměti na číslo, ale na datovou strukturu, která se skládá z několika položek a nás zajímá hodnota v
datové struktuře v položce3. Pak příkaz mov AX,[BP+položka3] naplní register AX obsahem položky3.
Položka3=bytová velikost Položky0+Položky1+Položky2
Přímé indexové adresování Je podobné jako Bázové relativní adresování
s tím rozdílem, že na místo bázový registrů používáme indexové registry SI a DI. Pak příkaz mov
AX,[ARRAY+SI] naplní register AX SI-tým prvkem pole. Tento způsob se využívá při práci poli a
řetězci.
Přerušení
Přerušení je způsob komunikace vnitřních nebo vnějších zařízení připojených k počítači. Jednoduchý,
ale nefektivní způsob je, pokud program obsluhuje pouze dané zařízení, ale to znamená, že program setrvává
v čekacích smyčkách a dle potřeby vykoná danou činnost. Lepším způsobem je, pokud program periodicky
kontroluje stav zařízení. Tento způsob zatěžuje procer neustálou kontrolou a tím snižuje výkon procesoru.
V současnosti se používá způsob, kdy harware zařízení vygeneruje signál - přerušení, proceror přeruší
vykonávání běžícího programu, obsouží zařízení a vrátí se k vykonávání původního programu. Procesor 80x86
obsahuje 256 přerušení, jsou uloženy na adrese 0000:0000 a každému vektoru přísluší 4 byty, ve kterých je
segmentová a ofstová část obslužné rutiny daného přerušení.
Přerušení od procesoru nazýváme interním přerušením, přerušení od vnějšího zařízení nazýváme externím
přerušením. Toto přerušení může být maskované a nemaskované. Maskované přerušení může programátor zakázat
příkazem CLI.
Přerušení 0 generuje procesor při dělení 0
Přerušení 1 generuje procesor př po rpovedení každé instrukce, pokud je nastaven příznak TF.
Přerušení 2 generuje procesor při nemaskovaném přerušení
Kompletní přehled přerušení je možné získat např. v prgramu sysman.
Speciální význam má přerušení 21h - přerušení systému MS-DOS, obecně fungují i pod Windows, ale
nové verze něktrá přerušení omezují (mění). Systém Linux většinou BIOS-přerušení nevyužívá, a
vše si obstarává sám.
základy assembleru
Syntaxe instrukce cíl,zdroj 0
Segmenty Jak je výše uvedeno, pamět je rozdělena na segmenty a
každý segment má velikost 64KB. Při psaní programu je potřeba definovat paměťový model. Pro většinu
prográmků mi stačil základní model TINY pro který platí, že kód+
data+zásobník musí být menší než 64KB. Popis ostatních paměťových modelů je v sekci
download. Správné rozdělení kódu, dat a zásobníku do paměti zajišťují
direktivyCODESEG, DATASEG a STACK.
Proměnné
direktiva |
velikost |
DB |
data byte - 8 bitů |
DW |
data word - 16 bitů |
DD |
data doubleword - 32 bitů |
DQ |
data quattroword |
DF |
FAR ukazatel - 6 bytů |
DP |
FAR ukazatel - 6 bytů |
DT |
reálná čísla - 10 bytů |
Spuštění programu Program je možné psát v obyčejném textovém
editoru a následně spustit. To znamená nejprve program zkompilovat (TASM.EXE) a tím sevytvoří
soubor *.obj a následně tento soubor slinkovat (TLINK.EXE) a tím vznikne EXE-soubour. Doporučuji
si najít nějaký assembler editor, který umožňuje psaní programů a zároveň jejich spuštění.
V sekci download jsou k dispozici.
příklady programu
načtení čísla, součet, převody
načtení znkau a práce s ním
načtení čísla, součet, převody
převede malé písmeno na velké
programování mikročipů