Aritmetické instrukce, zásobník

Tady není nutný žádný velký úvod, jdeme počítat a ukládat si čísla do zásoby.

Nyní přecházíme od početních instrukcí k zásobníku(englicky-stack). Zásobník je segment v paměti určený seg. registrem SS, na aktuální pozici(offset) ukazuje registr SP. zásobník je jákási skladovací díra. Představ si díru v zemi, do které si můžeš ukládat balíčky(čísla) nějakých věcí. Jeden balíček uložím na dno, druhý položím na ten první a pořád je dávám na sebe. Ovšem vyndavat je mohu pouze opačným způsobem, neboli můžu vzít vždy pouze ten shora. Nemohu si vyndat třeba z prostředka. To je naprosto jednoduchá, ale geniální věc. Například dva vnořené cykly-oba budou mít jako řídící proměnnou registr CX. Na začátku si nastavím CX na nějaké číslo a vlezu do prvního cyklu. Tam si CX uložím do zásobníku a nastavím ho na něco jiného(na počet opakování vnitřního cyklu) a vlezu do vnitřního cyklu. V něm se dějí různé věci, také si v něm třeba různě ukládam a vyndavám čísla ze zásobníku. Ale moje původní CX tam pořád je a já si ho po opuštění vnitřního cyklu vyzvednu, odečtu a pokud není nula, skočím na začátek prvního cyklu. A tak dále. Shrnuto, podtrženo-zásobník je jakýsi odkladový prostor. Abych nezapoměl-do zásobníku se ukládá odzhora, neboli při každém uložení WORDu se SP odečte o dva.

A má ještě jednu důležitou funkci-uplatňuje se při volání procedur(chceš-li tak funkcí) a do něj se také umísťují lokální proměnné a předávají se parametry funkcí předávané hodnotou(pokud jsou předávané odkazem-v Pascalu je před nimi VAR, je na ně v zásobníku pointer). Při volání funkce se nejprve do zásobníku uloží parametry v tom pořadí, v jakém jsou napsány v deklaraci a pak se pomocí instrukce CALL zavolá funkce. Instrukce CALL uloží do zásobníku adresu následující instrukce(adresa CS:IP) a skočí na funkci. Funkce si do registru BP uloží hodnotu SP, vyhradí si místo na lokální proměnné(které mají po překladu adresy typu SS:[BP+něco]). Po skončení funkce se provede MOV SP,BP a pak instrukce RET x.RET přečte ze zásobníku adresu uloženou instrukcí CALL, tak skočí a pak přičte k registru SP hodnotu x(která se v tomto případě rovná velikosti parametrů funkce-nechci přece, aby mi v zás. zůstaly a při každém volání funkce se jeho kapacita snižovala).


A jdeme na další procvičování ...
  1. Příklad č. 1
    "Spirála"

    Udělej program, který na obrazovku nakreslí spirálu. Začne se vlevo nahoře a budou se kreslit třeba hvězdičky postupně podél okraje obrazovky nejdřív doprava, pak dolů, doleva, nahoru, doprava ... Až do zaplnění obrazovky. Pro zájemce-na začátku můžeš uložit původní obsah obrazovky třeba do zásobníku(na PUSHovat tam celoou videoram, budou to 4 Kb) a po skončení a odklepnutí klávesy zase původní obraz obnovit.

    K tomuto programu vysvětlím další užitečnou věc-uspořádání videopaměti v textovém módu. Ve většině textových módů je videoram uložená v segmentu číslo 0B800H. Paměť je uspořádaná po řádkách(řádka má v normálním módu 80 znaků) a pro každý znak na obrazovce tam jsou dva byty-hodnotu znaku a barvu. To znamená, že znak vlevo nahoře je uložen na adrese 0B800H:0 a jeho barva na 0B800H:1. Ještě pro přesné pochopení uvedu třeba znak 3. řádce a 2. sloupci. Jeho adresa je tedy 0B800H:160*2+2 a barva je na 0B800H:160*2+3. Tolik tedy k textovému módu, na grafiku se podíváme později(možná).

  2. Příklad č. 2
    "Převod soustav"

    Napiš program, který si nechá zadat číslo v šestnáctkové soustavě a vypíše ho desítkově. To není nic jednoduchého. Předpokládám, že víš, jak se obecně převádí mezi číselnými soustavami a proto ti pouze ukážu způsob, jak se dá velice jednoduše převádět mezi dvojkovou(počítačovou) a šectnáctkovou soustavou:

    Kolik je vlastně číslo 16 ve dvojkové s. - je to 10000. Neboli rozsah šestnáckových číslic 0-F je dvojkově 0000-1111. To znamená, že poslední cifra šestnáctkového čísla se do dvojkového přenáší jako jeho poslední čtyři cifry. Obdobně to platí i u dalších cifer. druhá cifra šest. čísla je jako druhé čtyři cifry dvojkového. Proto nemusíš nějak obecně násobit mocninou čísla soustavy atd. Prostě vezmeš čtveřici bitů a převedeš ji pomocí tabulky šest. cifer na šect. číslo.

    Ve tvém programu ovšem potřebuješ nejen převést šestnáctkové číslo na dvojkové, ale poté ho musíš ještě předělat na desítkové. Tam už se ale bez dělení neobejdeš.

  3. Příklad č. 3
    "Trojúhelník"

    Tento výtvor by měl vypsat na obrazovku jakýsi trojúhelník. Na první řádku napíše jeden znak #219 = plný obdélník(nedonutil jsem windows, aby ho nějak stvořily). Na druhou řádku napíše dva, a tak dále až do 80. Pak to zase začne klesat. Zabere to 160 řádek, takže to celé pěkně pojede nahoru.

    Máš mnoho možností, jak to udělat. Buď pro každou řádku volat službu vypiš znak tolikrát, kolikrát je třeba nebo si můžeš nadefinovat řetězec dlouhý 81 znaků a obsahující samé znaky #219 a na konci znak "$" a měnit počáteční offsetu výpisu, čímž budeš vypisovat(službou 9) požadovaný počet znaků. Dokonce nemusíš vůbec používat služby na vypisování. Můžeš to dávat přímo do videoram, ale musel bys jí i scrollovat(posunovat) a to je podle mě zbytečně složité. Já jsem pro variantu č. 2.

Vzorová řešení

Úvodní stránka Registry procesoru Posuny a rotace
Rejstřík

Stránku připravuje Lukáš Valenta, 1. v celostátním kole soutěže v programování, kategorie mládež.