Učebnice Assembleru 86

Programátorský model mikroprocesoru 8086

Obvod 8086 je univerzální šestnáctibitový mikroprocesor. Má šestnáctibitovou ALU, to znamená, že je schopen provádět operace s šestnáctibitovými čísly. S okolím komunikuje po šestnáctibitové datové a dvacetibitové adresové sběrnici.

Segmentace paměti

Vzhledem k tomu, že obvod 8086 je schopen práce s pamětí o velikosti 1MB a obsahuje jen šestnáctibitové registry, je nutná tzv. segmentace paměti. Jedná se o logické dělení paměti do bloků po 64kB. Tomuto bloku říkáme segment a jeho počátek určuje programátor, případně je mu přidělen podle volného místa v paměti. Jediný požadavek na umístění počátku segmentu je, aby jeho adresa byla násobkem šestnácti. Umístění jednotlivých slabik v segmentu určuje offsetová část adresy (offset). Ta určuje, kolikátá je slabika od počátku segmentu. Adresa se skládá ze dvou částí: segment a offset. Obě tyto části jsou šestnáctibitové. Protože ale pro adresování paměti je nutné dvacet bitů, jsou za segmentovou adresu vyjádřenou binárně přidány čtyři bity s hodnotou nula (proto každý segment začíná na násobku šestnácti). K tomuto dvacetibitovému číslu je potom přičteno šestnáctibitové číslo určující offsetovou adresu. Takto vzniká dvacetibitové číslo znamenající skutečné umístění slabiky v paměti (fyzická adresa).

Výpočet skutečné adresy dvojkově:

segment:ssssssssssssssss0000
+offset:0000oooooooooooooooo
        --------------------
 adresa:aaaaaaaaaaaaaaaaaaaa

(segment jsou jednotlivé bity segmentové části adresy doplněné na konci o čtyři nuly, offset jsou jednotlivé bity offsetové části adresy doplněné na začátku o čtyři nuly, adresa je součet, tedy jednotlivé bity skutečné adresy)

Výpočet skutečné adresy hexadecimálně:

segment:ssss0
+offset:0oooo
        -----
 adresa:aaaaa

(segment jsou jednotlivé cifry segmentové části adresy doplněné na konci o jednu nulu, offset jsou jednotlivé cifry offsetové části adresy doplněné na začátku o jednu nulu, adresa je součet, tedy jednotlivé cifry skutečné adresy)

Například: Místo v paměti s adresou segmentu $AB1E a offsetu $1111 má skutečnou adresu:

segment:AB1E0
+offset:01111
        -----
 adresa:AC2F1

Tento způsob adresace umožňuje snadný přenos programu v paměti a jeho schopnost pracovat v každé její části. Program si pro svoji činnost vyčlení segment pro data, zásobník a strojový kód (instrukce). Na tyto bloky ukazují jednotlivé segmentové registry.

Důsledky segmentace:

  • přičteme-li k segmentové části adresy jedničku, zvýšíme skutečnou hodnotu adresy o šestnáct (což je to samé, jako bychom zvýšili offsetovou část adresy o šestnáct)
  • skutečnost, že se adresa tvoří součtem dvou čísel, vede k tomu, že stejné místo v paměti můžeme určit několika kombinacemi adres segmentu a offsetu dávajícími v součtu jeho fyzickou adresu

Pochopení segmentrace paměti je spíše ve znalosti dvojkové a šestnáctkové číselné soustavy.

POZOR!!! Neměli bychom zaměňovat pojmy segment a selektor. Segment určuje jen umístění bloku paměti. Selektor je použit u vyšších typů procesorů a jedná se vlastně o pořadové číslo v tabulce, která nese informace o vyčleněných místech paměti a jejich vlastnostech.

Z hlediska programátora jsou nejdůležitější registry. Ty se dělí na

  • registry pro všeobecné použití:
    • datové registry - šestnáctibitové (všechny vyhovují definici střadače), které je možné dělit na poloviny po osmi bitech, jejich použití bude probráno v dalších kapitolách:
      • AX (AH,AL) - střadač pro násobení a dělení, vstupně-výstuní operace
      • BX (BH,BL) - nepřímá adresace paměti (báze)
      • CX (CH,CL) - počitadlo při cyklech, posuvech a rotacích
      • DX (DH,DL) - nepřímá adresace vstupů/výstupů
    • ukazatele a indexregistry - pro umístění adresy (offsetu):
      • BP - bázový registr
      • SP - ukazatel zásobníku
      • DI - adresa cíle
      • SI - adresa zdroje
      • IP - ukazatel na aktuální místo programu
  • registr příznaků (F) - obsahuje šest bitů (indikátorů), které mikroprocesor nastavuje podle výsledku právě provedené operace, a umožňuje tak větvit program:
    • CF - Carry Flag, nastaví se do log. jedna, jestliže při právě provedené operaci došlo k přenosu z nejvyššího bitu osmibitového, nebo šestnáctibitového výsledku; tento indikátor je také využíván při posuvech a rotacích
    • PF - Parity Flag, se nastaví do log. jedna, pokud dolních osm bitů výsledku obsahuje sudý počet jedniček (a naopak)
    • AF - Auxiliary Carry Flag, nastaví se do log. jedna při přenosu 1 ze spodní poloviny nižší slabiky do vyšší; využívá se v BCD aritmetice (přenos do vyššího řádu)
    • ZF - Zero Flag, je v log. jedna při výsledku rovnému nule
    • SF - Sign Flag, je v log. jedna při záporném výsledku
    • OF - Overlow Flag, nastaví se do log. jedna, jestliže došlo k aritmetickému přetečení (výsledek se nevešel do cíle)

    Tyto registry se nastavují automaticky, jestliže proběhla instrukce, která je nastavuje. Registr F je doplněn i třemi řídicími registry, které ovlivňují běh programu:

    • TF - Trap Flag, jestliže je nastavený v log. jedna, mikroprocesor je uveden do krokovacího režimu; je tak umožněno odladění programu
    • IF - Interrupt Enable Flag, při log. jedna umožňuje vykonání maskovatelného přerušení, tzn. programovou obsluhu událostí
    • DF - Direction Flag, je určen k řízení směru zpracování řetězcových operací; při log. jedna se data zpracovávají sestupně (a naopak)

    Tyto tři registry může nastavit jen programátor vhodnými instrukcemi. Mikroprocesor je sám nenastavuje. Jestliže s registrem příznaků jako s celkem pracujeme, je šestnáctibitový a má tvar: X, X, X, X, OF, DF, IF, TF, SF, ZF, X, AF, X, PF, X, CF (bity X nejsou obsazeny)

  • segmentové registry - určené pro uložení druhé části adresy, segmentu:
    • DS - segment dat (proměnných)
    • ES - pomocný segment dat
    • SS - segment zásobníku
    • CS - segment programu

Mikroprocesor musí být schopen pracovat i se vstupy-výstupy. Umístění jednotlivých portů určuje šestnáctibitová adresa umístěná nejčastěji v registru DX. Pro programátora je důležitá i ta skutečnost, že si mikroprocesor vytváří tzv. frontu instrukcí. Jedná se o šest slabik znamenajících několik instrukcí, které budou následovat po právě prováděné instrukci. Tato fronta je průběžně doplňována při operacích nezatěžujících sběrnice z paměti. Protože se ale jedná o deset za sebou jdoucích slabik v paměti, je při instrukcích skoku v paměti vyprázdněna. Z tohoto důvodu je vhodné, aby program obsahoval co nejmenší počet skoků. Proto je v poslední době kladen důraz na programovací jazyky, které podporují tzv. strukturované programování bez nepodmíněných skoků. Mezi ně (částečně) patří Turbo Pascal a C. Je jasné, že programovací jazyk Basic se v tomto smyslu k mikroprocesoru nechová moc šetrně a zpomaluje tak běh programu. Mikroprocesor 80286 je strukturou i vlastnostmi podobný 8086. Je schopen pracovat ve dvou režimech. V základním reálném téměř přesně simuluje obvod 8086. Přesto v tomto režimu přináší některá rozšíření pro některé instrukce. Pokud v následujícím výkladu použiji rozšíření instrukcí pro 80286, uvedu to poznámkou [286]. Zdrojový text programu sestaveného i s pomocí instrukcí 80286 ve vkládaném assembleru stačí na prvním řádku (před uses) označit direktivou {$G+}.

Směr