|
|
|
KURZ STROJOVÉHO JAZYKA.
Pro uživatele každého počítače je důležité a užitečné, když se naučí systémový
vnitřní jazyk. Ale není to tak jednoduché, aby si mohl člověk jednoduše sednout
a začít programovat. Nejprve srovnejme znaky BASICu a strojového jazyka. V
BASICu je obsluha velmi pohodlná, protože např. programy pro počítání jako
*,+,-,/ jsou již definovány. U komfortnějších BASICů, jako je např. MZ-800 je
přirozeně definováno mnohem více funkcí jako např. SIN,COS,TAN,EXP atd. Naproti
tomu si ve strojovém jazyce musíme i obyčejné násobení dobře rozmyslet; opravdu
těžké jsou např. programy pro počítání v reálném čase. Hledisko rychlosti je
jeden z rozhoduj1icích argumentů pro programování v assembleru. A tak je někdy
zcela nemožné napsat některé programy v BASICu, protože rychlost je úplně
nedostačující. Totéž platí pro potřebu místa v paměti, která je u BASICu velmi
velká. Proti tomu se ve strojovém jazyce stejný problém vyřešit na jedné
desetině místa,zvláště, když se BASIC nemusí nahrávat. Toto uspoří při pozdějším
provádění programu mnoho času. Nyní ale začneme odhrnovat roušku tajemství
strojového jazyka.
1. Programovací medium.
Jako se v BASICu nedá programovat bez BASICu, nedá se programovat ve strojovém jazyce bez strojového jazyka. Zde je několik
možností:
A. programování v assembleru
B. programování ve strojovém jazyce
C. programování v Monitoru
Chceme zde jen ukázat rozdíly mezi assemblerem a strojovým
jazykem (zkráceně ML = machine language), ale dále se budeme zabývat programováním v ML (viz. též kniha: "ASSEMBLERPROGRAMMI-ERUBG AUF DEM MZ-700/800"). Proto vám doporučujeme, abyste si pro tento ML-kurs obstarali
dobrý strojový jazyk, který by měl v každém případě ovládat následující povely:
a. Disassembler
b. zapsání hex. čísla do paměti
c. listování pamětí
d. ukládání ASCII - řetězců do paměti (textwrite)
e. ASCII - listing
Toto vám umožní např. strojový jazyk 8002 od firmy BBG Software.
2. Dvojkový systém.
Pro znalce strojového jazyka mohou být následující kapitoly
příliš lehké a může je proto klidně přeskočit. Jestliže někomu
není dvojkový neboli binární systém známý, měl by zde dávat dobrý
pozor, protože toto je klíč k porozumění ML. Jak již jméno napovídá, jedná se zde o systém čísel, který má
něco společného s dvojkou (bi = řecky dvě). Jak možná víte, v elektronice a tím i u počítačů existují jen dva stavy, a to 0 a 1
(vypnuto a zapnuto). Tento dvojkový sytém používá jen tyto dva
stavy. Princip je podobný naší desítkové soustavě. Pro ty, kteří
náš desítkový systém ještě dostatečně neznají, máme jeden příklad. Vezměme si číslo 15326. Musíme zde jednotlivé číslice rozdělit podle jednotek, desítek, stovek,
tisíců atd. To znamená:
15326 = 1 deset tisíc ...... 1x10
3
5 tisíc ............ 5x10
2
3 sta .............. 3x10
1
2 desítky .......... 2x10
0
6 jednotek ......... 6x10 (pro všechny nematematiky: deset na nultou je jedna!)
4 3 2 1 0
15326 = 1x10 + 5x10 + 3x10 + 2x10 + 6x10
n n-1 n-2
číslo = Xx10 + Yx10 + Zx10 + Ax10 + Bx1
Právě tak se chová dvojkový systém. Desítkový systém má za
základ 10, dvojkový systém 2. U desítkového systému je největší
číslice 9, u dvojkového systému tomu odpovídající číslo 1. Jsou
zde tedy pouze číslice 0 a 1.
n n-1 n-2
dv.č. = Xx2 + Yx2 + Zx2 + Ax2x1 + Bx1
Jako příklad přepočítáme decimální číslo 39 na binární. Na to
musíme znát mocniny dvojky. Tak jako 10,100,1000,10000 atd. jsou
mocniny deseti, tak jsou 2,4,8,16,32,64,128 atd. mocniny dvojky.
x
číslo = 2 = mocnina 2
x
číslo = 10 = mocnina 10
Číslo 39 se skládá z mocnin 2, následujícím způsobem:
39 = 32 + 4 + 2 + 1
5 2 1 0
39 = 2 + 2 + 2 + 2
To se pokusíme zvládnout nejlépe pomocí následující tabulky:
-----------------------------------------------------------------
128 64 32 16 8 4 2 1
0 0 1 0 0 1 1 1 = 39
-----------------------------------------------------------------
Decimální číslo 39 se v binární soustavě rovná číslu 00100111.
Jako jiný příklad decimální číslo 111. Sestavíme opět tabulku tak,
že zapíšeme pod příslušnou mocninu 2 jedničku nebo nulu, aby
vzniklo správné číslo.
-----------------------------------------------------------------
128 64 32 16 8 4 2 1
0 1 1 0 1 1 1 1 = 111
-----------------------------------------------------------------
Decimální číslo 111 je tedy v binární soustavě 01101111.
Předkládáme vám ale ještě jednu dobrou metodu, jak určit, kdy
se musí pod mocninu 2 napsat 0 nebo 1. Ukážeme si to opět na čísle 111. Nejdříve hledáme mocninu 2,
která je nejbližší nižší k desítkovému číslu. 128 je větší než
111, ale zároveň je číslo 111 větší než číslo 64. Napíšeme tedy
pod 64 číslo 1, a potom 64 odečteme od 111 (111 - 64 = 47). Nyní
zacházíme s číslem 47 právě tak, jako s číslem 111, takže 32 by
bylo nejbližší nižší mocnina 2. Zapíšeme tedy pod 32 číslo 1 a
odčítáme (47 - 32 = 15). Příští nejbližší nižší mocnina 2 je 8,
takže pod ní zapíšeme 1, odečtením dostaneme 7, což se dá z hlavy spočítat jako dvojkové číslo 111 (1 + 2 + 4 = 7). Tam, kam nebyla
zapsána žádná 1, je logicky zapsána 0. Tím dostaneme dvojkové číslo 01101111.
Čím větší je decimální číslo, tím větší musí být mocniny 2. Jestliže máme dvojkové číslo a chceme ho přepočítat na desítkové, sečteme jednoduše mocniny 2. To může sloužit jako kontrola
např. 01101111 = 64 + 32 + 8 + 4 + 2 + 1 = 111.
3. Hexadecimální systém.
Hexadecimální systém se může z počátku zdát pro začátečníka zmatený, ale přesto
je to velice logický systém a základ pro naučení strojového jazyka. Ptáte se proč se za základ pro počítač
nevzal desítkový nebo dvojkový systém. Odpověď je zřejmá.
Desítkový
systém není pro počítač zpracovatelný, a přepočítávaní desítkového systému do dvojkového spotřebuje mnoho času.
Přepočítávání hexadecimálního systému do dvojkového je velice rychlé, protože 16 je přece mocnina 2. Tím se ještě budeme zabývat. Jak již
jméno napovídá, je číslo 16 základ tohoto číselného systému. Obecná přepočtová rovnice tedy tentokrát zní:
n n-1 n-2
číslo = Zx16 + Yx16 + Zx16 + Ax16
Mocniny 16 jsou:
0 1 2 3
1, 16, 256, 4096 = 16 ,16 ,16 ,16
Potřebujeme jen tyto mocniny, protože v paměti můžeme adresovat jen po 63 535, takže vyšší mocninu nepotřebujeme. Pravděpodobně vás již napadlo, jak jak může být hexadecimální systém vybaven číslicemi, když od 10 do 15 žádné číslice nejsou. Zde bylo rozhodnuto vzít za základ písmena A - F, takže A=10,B=11, C=12, D=13, E=15. Výpočet hexadecimálního čísla se provádí
podle stejného schématu jako při výpočtu dvojkového čísla. Jenom
se zde samozřejmě hledá nejbližší nižší mocnina 16. Podívejme se
na to na příkladu. Decimální číslo 83 má být přepočítáno na hexadecimální.
Nejdříve tedy napíšeme tabulku:
-----------------------------------------
4096 256 16 1
0 0 5 3 = 83
-----------------------------------------
Postupujme analogicky k dvojkovému systému. Nejprve hledáme
nejbližší nižší mocninu 16, čili číslo 16. Toto je v 83 obsaženo
5 krát, napíšeme tedy pod 16 číslo 5, 5x16=80, dostaneme tedy zbytek 3. Dohromady to tedy dává hexadecimální číslo 83. Zkusme to
na větším decimálním čísle, třeba 15311. Nejlépe bude, vezmete-li
si na pomoc kapesní kalkulačku. První mocnina je 4096. Toto číslo
je v 15311 obsaženo 3x, 3x4096=12288. Nyní dostaneme jeho zbytek
(15311-12288) 3023, který musíme porovnat s další menší mocninou
16. Do 3023 se 256 vejde 11x. Nyní musíme opět spočítat zbytek
(3023-(11x256)=207). 207 děleno 16 je 12 a zbytek je 15.
-------------------------------------------------
15311 = 3x4096 + 11x256 + 12x16 + 15
3 2 1 0
15311 = 3x16 + 11x16 + 12x16 + 15x16
-------------------------------------------------
Nyní musíme čísla přeformovat na hexadecimální čísla. Jak
jsme se již zmínili, představují čísla přes 9 samostatné hexadecimální cifry(A=10,B=11 atd.). Nyní musíme vypočtené hodnoty čili
3,11,12,15 přeformovat na hexadecimální číslo, což dává 3BCF.
Nejvyšší hexadecimální hodnota by byla FFFF. Od teď budou hexadecimální čísla na konci označena písmenem H. To nám také ulehčí
identifikaci, zda se jedná o čísla mající decimální nebo hexadecimální hodnotu. FFFFH je tedy 15x4096 + 15x256 + 15x16 + 15=65535.
Volné místo v paměti je 65535 bytů, což je 64 Kbytů.
3.1. Přepočítání z dvojkové do hexadecimální soustavy.
Při programování ve strojovém jazyce je později důležité převádět dvojkové
hodnoty na hexadecimální a naopak. K tomu několik dobrých rad: budeme se zde zabývat jen 8-bitovými hodnotami, např. dvojkovou hodnotou 01111111. Potom se 8-bitové číslo
rozdělí na dvě poloviny, a to přesně uprostřed a vznikne 0111 a
1111. To jsou decimální čísla 7, resp. 15, což jsou hexadecimální hodnoty 7 a F. Hexadecimální číslo tedy je 7FH.
4. Bit a byte.
S těmito pojmy jsme se již setkali občas v předcházejících kapitolách. Kdo ještě
neví oč se jedná, tomu budiž řečeno následující. Bit je nejmenší jednotka, kterou počítač zná. Byte se
skládá z 8 bitů. Bity si mohou pamatovat jen stavy 0 a 1, jeden
byte má proti tomu 2 na osmou, tj. 256 možností zapamatování.
Byte je normálně udáván jako hexadecimální číslo. Celá paměť
MZ-800 má podle toho 8x65535 = 524280 bitů.
5.Procesor Z-80.
Mikroprocesor Z-80 je srdcem MZ-800. Každý počítač má mikroprocesor, ATARI, APPLE, COMMODORE mají především procesory 6502.
Jiné známé procesory jsou 6809 a nové 32-bitové procesory 68000,
80186 a mnoho dalších. Z-80 procesor má asi 400 oficiálních povelů a ještě
mnohem více neznámých povelů, kterými se budeme zabývat později. Povely jsou 1,2,3,4 bytové.
5.1. Registry.
Registry jsou zvláštností procesoru. S registry se dá počítat, vyjímat hodnoty z paměti a přenášet hodnoty do paměti. Mnoho logických operací, sčítání, odčítání a další se provádí pomocí registrů. Přitom existují jednobytové a dvoubytové registry.
Dvoubytové neboli také 16 bitové registry jsou zvláště praktické
pro matematické operace. To je výhoda, kterou má procesor Z-80
proti procesoru 6502.
Sada registrů:
8-bitové registry 16-bitové registry
----------------- ------------------
A (akumulátor) PC (programmcounter-čítač programů)
B BC (skládá se dohromady
C z B a C)
D DE (skládá se
E z D a E)
H HL (skládá se
L z H a L)
F (příznak přepínače) SP (ukazatel zásobníku)
LX IX (skládá se z
HX registrů LX a HX)
LY IY (skládá se z
HY registrů LY a HY)
Dvojitý registr z A,B,C,D,E,F,H,L
R - obnovovací registr
I - přerušovací registr
5.1.1. Akumulátor (A-registr).
Jak již bylo naznačeno, má akumulátor mezi registry zvláštní
postavení. Akumulátor je 8-bitový registr, ve kterém se provádí
logické operace jako AND,OR, ale též sčítání a odčítání. Jako
jediný 8-bitový registr je schopen vyvolat hodnoty z paměti a do
paměti je ukládat. Logické operace může provádět s pomocí ostatních
registrů nebo s pamětí. To dělá z akumulátoru důležitou součástí
procesoru.
5.1.2. Další 8-bitové registry.
Kromě akumulátoru má Z-80 ještě další registry, jako B,C,D,E,H,L. Obecně působí tyto registry jako akumulátor, ale jejich zásoba povelů není tak velká. A tak mohou pracovat jen ve spojení
s akumulátorem. Také není možné adresování paměti z těchto registrů.
5.1.3. Příznaky přepínače (flags).
Příznaky přepínače jsou představovány F-registrem, takže je dohromady 8 příznaků přepínače, z kterých je používáno pouze 6.
Zde je grafický přehled:
--------------------------------------------
7 6 5 4 3 2 1 0
S Z - H - P N C
--------------------------------------------
Jména flagů:
S - znaménkový flag
Z - nulový flag
H - poloviční indikátor přenosu
P - paritní flag
N - odčítací flag
C - indikátor přenosu
Flagy se používají pro označení výsledku matematicko-aritmetické operace. Udává se, zda operace dává výsledek jako 0, nebo
jestli existuje přeplnění atd.
5.1.3.1. Indikátor přenosu.
Indikátor přenosu nám ukazuje přeplnění bitu 7 (u 16-bitových
přeplnění bitu 15). Indikátor přenosu si můžeme představit jako
aktivní devátý bit. Chceme provést operaci, při které vznikne
přeplnění 8-bitů, takže při ní překročíme výpočetní oblast. Např.A obsahuje 83H a B obsahuje 90H. Součet dává potom 113H, což by
bylo ale 9-bitové číslo. V akumulátoru je potom 13H a v indikátoru přenosu 1.
5.1.3.2. Odečítací flag.
Tento příznak přepínače není programátorem požíván, používá se
při speciálních desítkově-aritmetických povelech jako vnitřní
znaménkový bit. Pro programování je relativně nedůležitý.
5.1.3.3. Poloviční indikátor přenosu.
Poloviční indikátor přenosu funguje podobně jako indikátor
přenosu, ale ukazuje se zde přenosu ze 3 bitů na 4. Pro programátora zpracovávajícího program ve strojovém jazyce zde není žádná
možnost tento indikátor kontrolovat, a proto je praktický význam
minimální.
5.1.3.4. Paritní flag.
Paritní flag má 2 hlavní funkce.
a) Určení rovnosti nějakého jevu. Rovnost znamená totéž jako křížový součet. To znamená, že se spočítají jednotky uvnitř jednoho bytu. Jestliže se suma jednotek nerovná, potom je v P-flagu
jednotka (1), jinak je obnoven počáteční stav.
b) Druhá hlavní funkce je funkce přeplnění. Udává se, zda při sčítání nebo odčítání nebyl omylem změněn znaménkový bit tím, že výsledek omylem přeběhl do znaménkového bitu.
5.1.3.5. Zero-flag.
Jak jsme se již zmínili ve výše uvedeném příkladu, slouží
nulový flag k zobrazení toho, zda některá operace má výsledek 0
nebo ne. Při výsledku 0 má Z-flag nastaveno 1, jinak 0.
5.1.3.6. Znaménkový flag.
Tento flag slouží k zobrazení znaménka, přičemž se osmice
bitů rozdělí na 7 datových bitů a jeden bit znaménkový. To má za
následek to, že výpočetní oblast je od -127 do +128.
5.1.4. R - registr.
Obnovovací registr slouží interně k obnovení paměti. Přitom počítadlo odpočítává
z 7FH na 0, a potom je paměti vydán obnovovací impuls. Z tohoto registru se dá prakticky jen číst, což se
však báječně hodí pro generátor náhodných čísel. Tím, že se zamezí impulsu obnovení (do akumulátoru se dá xx a do R se dá A) se
dá vymazat celá paměť a zůstane pouze destruktivní program.
5.1.5. I - registr.
Přerušovací registr ukazuje stav uvnitř úrovně operačního
systému, takže pro programátora nemá velký praktický význam.
5.1.6. PC - registr.
PC-registr, nebo též čítač programů, ukazuje, na kterém místě
právě pracuje základní jednotka Z-80. K čítači programů není možný
žádný přímý přístup.
5.1.7. SP - registr.
SP-registr, nebo též ukazatel zásobníku, je registr, ve kterém je 16-bitová adresa místa v paměti. Na tomto místě se nachází
zásobník, což je pomocí ukazatele zásobníku definovaná pracovní
oblast, do které se ukládají, a ze které se vybírají data. Pro
práci s tímto zásobníkem jsou speciální povely, kterými se budeme
zabývat později.
5.1.8. HL - registr.
HL-registr je 16-bitový registr, který se skládá ze dvou 8-bitových registrů H a L. Přitom nižší byt (Low Byte) tvoří L,
zatím co vyšší byt (High Byte) tvoří H.
Pro osvěžení:
Low znamenalo nižší, High vyšší hodnotu. Zde začínáme mluvit o
něčem, na co se v 16-bitovém zápisu musí dávat pozor. V paměti je
nejprve uložen Low, a potom High registr. Nechť tedy obsahuje
H-registr 06H, L-registr F4H. Potom bude registr HL obsahovat jako
celek O6F4H. Jestliže nyní uložíme obsah registru HL do paměti, bude v paměti stát F406, čili přesně obráceně. HL-registr je tedy
16-bitový registr pro logické operace, a je to vedle A nejpoužívanější registr v sadě registrů.
5.1.9. BC a DE - registry.
Tyto dva registry jsou velmi podobné registru HL. Oba se
skládají z 8-bitových registrů B a C, resp. D a E, ale povelový
komfort je ve srovnání s HL velmi omezený. Musí se dát ale velký
pozor na to, že když se při programování použije registr B, změní
se i hodnota registru BC, takže se nejprve musí zachránit hodnota
registru BC. To je chyba, která se při programování ve strojovém jazyce často
stává. To samozřejmě platí pro všechny 16-bitové registry, takže i pro HL,DF,IX,IY.
5.1.10. IX a IY registry.
Registry IX a IY jsou velcí bratři registru HL. Zde se musí
dát pozor, protože zde bylo trochu nešťastně zvoleno pojmenování
registrů. Za prvé nemají registry IY a IX nic společného s registrem I. Část I z IX registru je HX
registr, část X je LX registr. Právě tak je to u IY registru, kde I je HY, část Y je LY
registr. Pozor ale na to, že LY,HY,HX,LX jsou 8-bitové registry,
a ne jak se může na první pohled zdát 16-bitové registry. Programování těchto registrů není popsáno v žádné knize o Z-80, jsou to
neznámé povely, kterými se budeme zabývat později. IX a IY se též nazývají
indexové registry. Sada povelů indexových registrů je
velice podobná povelům pro HL registr, ale pro každý povel pro
indexový registr je potřeba minimálně tři, většinou dokonce čtyři
byty, což značně zvětšuje délku programu. O způsobu adresování
budeme mluvit v jiné kapitole, protože je to opravdu těžká část
programování ve strojovém jazyce.
5.1.11. Zdvojené registry.
Zvláštností v sadě registrů jsou tzv. zdvojené registry, A',B',C',D',E',H',L',F'. Jsou to duplikáty registrů A,B,C,D,E,H,L,F,
které byly vyměněny s normálními registry pomocí povelů pro vyměňování. Procesor dále počítá s hodnotami zdvojených registrů.
Jestliže se povely vyměňování požijí dvakrát, logicky se vytvoří
původní stav.
5.2. Mnemonic a Opcode.
Další důležitou kapitolou je souvislost mezi symbolem a významem povelů ve strojovém jazyce. Právě tak jako v BASICu má i zde
každý povel konkrétní význam. Tak např. povel DIM v BASICu má
význam zřízení pole. Ve strojovém jazyce má také každý povel svůj
hexa. kód, čili hexa. číslo označuje povel. Tak povel NOP
(No OPeration) je označen číslem 00H. Takže když je zpracovávána
hodnota 00H, je interpretována jako NOP, a potom zpracovává ihned
další povel. Jestliže přijde jako povel 09H, budou sečteny registry HL a BC.
Přehled všech těchto povelů Z-80 najdete v dodatku této knihy. Mnemoniccode 09H znamená ADD HL,BC, čímž se dostáváme k mnemotechnickému způsobu zápisu. Mnemoniccode povelu je pro
programátora srozumitelná interpretace hexa. povelu. Tak je pro
hexa. povel 09H definován mnemoniccode ADD HL,BL. Pro programátora není možné rozpoznat smysl programu jen na základě čísel,
naproti tomu mnemoniccode je pro něj snadno srozumitelný. V mnemoniccode se dá programovat, ovšem pouze v assembleru. V assembleru programujete např. INC
A a assembler to převede na 3CH.
Disassembler dělá pravý opak, takže převede 3CH na INC A. Pro nás
je disassembler plně dostačující, ale každý dobrý stroj. jazyk
by měl mít disassembler. Program se vloží v hexa. číslech a
potom se může vylistovat pomocí disassembleru. Programování v
assembleru je rozsáhlejší, ale má také více možností.
5.3. Struktura paměti
Napsaný program je v paměti na určité adrese. Paměť začíná
na adrese 0000H a končí na FFFFH. Normální oblast programování
MZ-800 začíná na 1200H. Odtud budeme též psát všechny naše programy. Ke každé adrese v paměti patří také obsah, což může být datový
nebo programový byte. Abychom se mohli tímto zabývat, potřebujeme disassembler, který přeloží ze strojového jazyka do jazyka
symbolických instrukcí oblast od 1200H. Když se zapne počítač,
nejprve se většinou vymaže paměť. Je tomu tak i u MZ-800. Nyní
tedy nalézáme v paměti pouze 00H a FFH. Když uvedený obsah přeložíme, objeví se následující:
ADRESA OPCODE MNEMONICCODE
1200 00 NOP
1201 00 NOP
1202 FF RST 38
1203 FF RST 38
5.4. Druhy
adresování.
V možnostech adresování není Z-80 vybaven tak bohatě jako
jeho protějšek - 6502. Přesto zde musíme říci několik věcí ne
právě zanedbatelného významu. U Z-80 má mnemoiccode tři díly:
a) druh povelu
b) cílová adresa / registr
c) strojová adresa / registr
To znázorníme na příkladu:
Příklad: LD A,B
Toto je ukládací povel, při kterém bude hodnota, která je v
registru B uložena do registru A. V BASICu by tento povel zněl:
A = B. Na tomto se dá vysvětlit struktura mnemonického kódu. Druh
povelu je ukládací povel (LD). Cílový registr je zde A-registr,
zdrojový registr je B-registr. To je registrové adresování. Zabývejme se nyní povelem LD A,(HL), což je opět ukládací povel. Akumulátor zde opět představuje cílový registr. Jen zdrojový registr
zde potřebuje další vysvětlení. Vidíme, že zdrojový výraz je zde
(HL). Závorka nám ukazuje, že zde pracujeme s pamětí. Výraz v závorce je HL-registr. HL je 16-bitový registr, který zde ukazuje
na místo v paměti. Jestliže by HL měl hodnotu 0000H, pak by byla
zpracovávána hodnota, která je v paměti na místě 0000H (u MZ-800
je na adrese 0000H C3H). Tato hodnota je potom uložena do akumulátoru. A ještě další příklad:
LD (1000H),A
Jedná se opět o ukládací příkaz. Tentokrát nám závorka ukazuje, že cílová adresa je v paměti, zde tedy adresa 1000H. Hodnota,
která má být uložena za adresu 1000H, je tedy v akumulátoru
(zdrojovém registru). Rozdílné jsou 16-bitové ukládací povely. Vezměme příklad uvedený výše, ale tentokrát s HL-registrem.
LD (1000H),HL
Jak si můžete domyslet, bude hodnota v HL-registru uložena na
adrese 1000H. Nyní je ale tato hodnota 16-bitová, takže obsadí
kromě adresy 1000H ještě adresu 1001H. Jak jsme se již zmínily, při 16-bitových znacích se v paměti
ukládá nejprve nižší a potom vyšší byte. Nechť HL obsahuje před
provedením příkazu LD (1000H),HL hodnotu 12F5H. Po provedení je
na adrese 1000H hodnota F5H, na adrese 1001H hodnota 12.
Jako poslední bychom se chtěli zabývat dříve zmíněným indexovým adresováním registrů IX a IY. Jak již bylo řečeno, můžeme tyto
registry považovat za velké bratry registru HL. Pro IX platí hexadecimální označení DDH, pro IY platí označení FDH. K hexa. kódu, který platí pro HL, se jednoduše přidá DDH nebo FDH. Jako
příklad uvedeme povel INC HL:
INC HL = 23
INC IX = DD 23
INC IY = FD 23
To platí jen pro ty povely, u kterých nejsou žádné cílové a
zdrojové pohyby, protože tam musí být ještě hodnota indexu. Po
Opcode se přidá ještě jeden byte.
Zabývejme se např. povelem:
LD A,(IX+05)
Tento povel má velkou vnější podobu s již zmíněným příkladem
LD A,(HL), jen je tentokrát jiná hodnota výrazu v závorce; místo
HL je zde IX+05. Jestliže tedy IX obsahuje hodnotu 2000H, přičte
se k ní 5 a dostaneme hodnotu 2005H. Potom bude vybrána hodnota
z adresy 2005Ha bude uložena do akumulátoru.
5.4.1. Výpočet indexového adresování.
Rozhodující je výpočet indexové hodnoty za Opcode, protože
např. existuje povel LD A,(IX-03). Můžete se domyslet, že při
indexovém adresování přicházejí v úvahu hodnoty v rozsahu od -128
do +127. Jako další příklad uvedeme povel:
LD A,(IX+F0H)
Při hexa. hodnotě F0 je nastaven sedmý bit. Tento sedmý bit
je znaménkový bit - to znamená, že to je záporné číslo. V tomto
případě se jednoduše hodnota neguje (vytvoří se doplněk); doplněk
k FOH je 10H (F0H + 10H = 00H). Takže kdyby IX bylo 2000H, od
2000H by se odečetlo 10H, což dává 1FF0H. Z této adresy by byl
obsah uložen do akumulátoru.
Příklady:
IX hodnota Hodnota indexu Vytvořená adresa
3000H 10H 3010H
3000H 00H 3000H
3000H C0H 2FC0H
Ještě nezkušený programátor by měl nejprve znát všechny hodnoty HL-registru, než začne s indexovým programováním.
5.6. Dvojková aritmetika.
Dvojková logika je ve strojovém jazyce důležitá věc. Většinou
jde o logické operace s akumulátorem, se kterým se dají lépe
rozpoznat nebo maskovat určité stavu bitu.
Povely logických operací jsou:
a) AND
b) OR
c) XOR
Nejprve něco o základu logických operací. Provádí se vždy logické operace se dvěma bity podle logického schématu. Cílový bit bude obsahovat
novou hodnotu, přičemž se postupuje podle tabulek.
Například tabulka příkazu OR
bit A bit B výsledný bit
----------------------------
0 0 0
1 0 1
0 1 1
1 1 1
Na vysvětlenou: Když má bit A hodnotu 1 a bit B hodnotu 0, bude mít výsledný bit logické operace hodnotu 1.
Když bude mít bit A, nebo B hodnotu 1, bude výsledný také 1. Ve
strojovém jazyce se provádějí logické operace vždy v akumulátoru
s jedním s registrů. Například logická operace OR A,B, nebo lépe
uspořádáno OR(AaB). Výsledek log. operace je také v akumulátoru.
Proveďme operaci OR v akumulátoru a C registru. A obsahuje 45H a
C obsahuje 09H. Nyní napište tyto hodnoty ve dvojkovém kódu.
registr A 01000101 45H
C 00001001 09H
---------------
výsledek 01001101 4DH
Porovnávali jsme pod sebou napsané bity podle tabulky OR, a jako
výsledek jsme dostali 4DH.
Nyní tabulka pro příkaz AND
bit A bit B výsledný bit
--------------------------------
0 0 0
0 1 0
1 0 0
1 1 1
Vezměte nahoře uvedená data a porovnejte podle tabulky AND.
registr A 01000101 45H C 00001001 09H
-------------------
výsledek 00000001 01H
Po provedení AND A,B je tedy v akumulátoru hodnota 01H. Při log.
operaci AND bude výsledek 1, pouze tehdy, když oba původní bity
obsahují 1.
Nakonec ještě tabulka pro příkaz XOR.
bit A bit B výsledný bit
--------------------------------
0 0 0
0 1 1
1 0 1
1 1 0
Znovu porovnáváme uvedená data pomocí tabulky XOR
registr A 01000101 45H
C 00001001 09H
-------------------
výsledek 01001100 4CH
Po provedení příkazu XOR A,B obsahuje akumulátor hodnotu 4CH.
Příkaz XOR dá interpretovat také takto. Výsledný bit obsahuje
1 pouze tehdy, když bity A,B jsou rozdílné.
5.7. Logické a početní operace
V sadě příkazů je několik příkazů, které programátorovi
při těchto operacích pomáhají
5.7.1. Příkaz ADD
Příkaz ADD je jednoduchý sčítací příkaz, který sčítá dva
registry. Například ADD HL,BC. Když HL obsahuje 3245H a BC A753H,
pak po provedení příkazu obsahuje HL registr hodnotu D998H.
5.7.2. Příkaz ADC
Příkaz ADC pracuje stejně jako ADD, ale při sčítání je přičten
i indikátor přenosu. Kdyby byl indikátor nastaven a provedli
bychom příkaz ADC HL,BC s hodnotami dříve uvedenými, v registru HL
by byl výsledek D999H.
5.7.3. Příkaz SUB
Příkaz SUB vzájemně odečítá dva 8-bitové registry. Například
příkaz SUB A,B odečítá registr B od akumulátoru.
5.7.4. Příkaz SBC
Příkaz SBC pracuje stejně jako příkaz SUB, ale při nastavení
indikátoru přenosu je odečten i indikátor přenosu. SBC příkaz
platí na rozdíl od příkazu SUB i pro 16-bitové registry.
5.7.5. Příkaz INC
Příkaz INC jednoduše načítá registr, to znamená, že je jeho
hodnota o jednotku zvýšena. Když HL obsahuje 3323H, po provedení příkazu INC HL bude obsahovat hodnotu 3324H. Podobně jako
v BASICu X=X+1.
5.7.6. Příkaz DEC
Příkaz DEC jednoduše odčítává registr, to znamená, že jeho
hodnota je o jednotku snížena. Když HL obsahuje 3323H, po provedení příkazu DEC HL bude obsahovat hodnotu 3322H. Podobně jako
v BASICu X=X-1.
5.7.7. Příkaz CP
Příkaz CP umožňuje srovnávat registr nebo obsah paměti s
akumulátorem. Srovnává se, zda hodnota v akumulátoru je větší,
menší nebo stejná. Například registry A i B obsahují hodnotu
99H. Po provedení příkazu CP A,B se v registrech hodnoty nemění,
ale nastaven Zero-flag, protože hodnoty se sobě rovnají.
5.8. Práce s jednotlivými bity
V sadě příkazů jsou příkazy, které umožňují zjišťování hodnot,
nastavení nebo obnovení počátečních hodnot jednotlivých bitů.
5.8.1. Příkaz SET
Příkaz umožňuje nastavení jednotlivých bitů v registrech.
Například SET 7,A nastavuje nejvyšší bit v akumulátoru na 1.
Může se manipulovat i s hodnotou v paměti pomocí indexového
adresování.
5.8.2. Příkaz RES
Příkaz RES umožňuje nastavení počáteční hodnoty jednotlivých
bitů v registrech. Například RES 5,B nastavuje pátý bit registru B
na 0. Jestliže B obsahoval předtím 23H (00100011), obsahuje po
provedení příkazu hodnotu 03H (00000011)
5.8.3. Příkaz BIT
Příkaz BIT umožňuje zjišťování hodnot jednotlivých bitů v
registrech. Například BIT 0,A zde se zjišťuje obsah nultého bitu
akumulátoru. Tato část hodnoty je potom v Z-flagu. Jestliže
nultý bit akumulátoru obsahoval 1, pak v Z-flagu je 0.
5.8.4. Příkazy rotací
Příkazy rotací jsou příkazy, pomocí kterých můžeme bity
v registrech rolovat, to znamená, že při levotočivé rotaci se
6-tý bit přesune na místo 7-mého bitu, 5-tý bit na místo 6-tého
bitu atd. až se přesune 7-mý bit na místo 0-tého bitu. Při
pravotočivé rotaci se budou bity posouvat obráceně. Příkazy
rotace se liší jen nepatrně. Co bude pro programátory Z-80
jistě nové, je příkaz SLS (CB30 až CB37 jako Opcode). Většinou
se obejdeme s příkazy RRCA a RLCA. Zde se ještě zmíníme o použití
při násobení. Vezměme si např. číslo 52, napišme ho v binárním
kódu 00110100. Když provedeme RRCA, bude po rotaci v akumulátoru
01101000, což je číslo 104. Provedlo se násobení dvěma. Jestliže
byl nastaven 7 bit, výsledek není správný! Přeplnění je v flagu
CY. Pávě tak otáčení doprava znamená dělení. Proto jsou tyto
příkazy zvláště při matematických programech nepostradatelné.
5.8.5. Blokové příkazy
Mikroprocesor Z-80 má tu zvláštnost, že může použít příkazy
pro operace s bloky. Tyto příkazy se dělí do dvou skupin.
a) příkazy pro hledání bloků
b) příkazy pro přesuny bloků
5.8.5.1. Příkazy pro hledání bloků
Hledání bloků zde bude vysvětleno na příkazu CPIR. Přitom se
znak, který je v akumulátoru, hledá v určité oblasti. Adresa
začátku je v HL, délka bloku, ve kterém se má hledat je v BC a
znak, který se bude hledat je v akumulátoru. Například budeme
hledat znak 66H v oblasti od 3000H do 4000H. Jestliže je znak
nalezen, bude práce na tomto místě v paměti přerušena a Z-flag je nastaven.
Jestliže znak není nalezen, je Z-flag nastaven na
původní hodnotu.
1200 3E 66 LD A,66H
1202 21 00 30 LD HL,3000H
1205 01 00 10 LD BC,1000H
1208 ED B1 CPIR
120A CA XX XX JP Z,XXXXH
120D pokračování
5.8.5.2. Příkazy přesunu bloků
Funkce přesunu bloků bude vysvětlena na příkazu LDIR. Přitom
bude blok v paměti přesunut do jiné části paměti. Budeme
přesouvat
oblast od 2000H do 3000H za C000H. Pro příkaz LDIR jsou třeba tři
parametry:
a) počáteční adresa původního bloku HL - registr
b) počáteční adresa přesunu DE - registr
c) délka bloku BC - registr
Jsou-li nastaveny všechny parametry, můžeme použít příkaz
LDIR. Pro shora uvedená data by se musel napsat následující
program:
1200 21 00 20 LD HL,2000H odkud
1203 11 00 C0 LD DE,C000H kam
1206 01 00 10 LD BC,1000H délka
1209 ED B0 LDIR
120B C3 AD 00 JP 00ADH skok do monitoru
5.8.6. Příkazy skoků
Zásadně jsou dva druhy skoků, podmíněné a nepodmíněné.
Nepodmíněné skoky "skáčí" vždy na definovanou adresu, podmíněné
skoky "skáčí" na adresu pouze tehdy, je-li splněna podmínka, např.
když je Z-flag 1.
5.8.6.1. Absolutní příkazy skoků
Absolutní příkazy skoků jsou jednoduché příkazy, například
JP 3000H skočí vždy na adresu 3000H v paměti, nebo například
JP NZ,3000H skáčí na adresu 3000H, když výsledek operace není
nulový,bude v Z-flagu 0. N v podmínce znamená vždy NE !!
Například: NC = not Carry
5.8.6.2. Relativní příkazy skoků
Relativní příkazy skoků jsou o něco komplikovanější než
absolutní. Jsou také podmíněné a nepodmíněné, ale způsob
adresování je jiný. Podobá se indexovému adresování, popsanému
v kapitole 5.4.1.. Jak si vzpomínáme, rozsah hodnot byl od -128
do 127, čili 7-mi bitové zobrazení. Právě tak je to u relativního
skoku. Nejprve následuje normální byt pro druh příkazu, potom
hodnota indexu, například
1200 38 06 JR C,PC+2+06 ;PC - obsah čítače instrukcí
V tomto případě bude pokračovat zpracování programu o 6 bytů dále,
je-li nastaven indikátor přenosu. Výhoda relativních skoků je
možnost přesunutí do libovolné oblasti paměti. Naproti tomu je
nevýhodou malý rozsah adresování pouze 256 bytů, což hovoří pro
absolutní adresování. Zvláštní formou je skok závislý na registru
například JP (HL). To znamená, že ve zpracování programu se bude pokračovat na
tom místě v paměti, které odpovídá hodnotě registru HL. Jestliže
HL obsahuje například hodnotu 2000H, stačí na adresu 2000H. To
platí i pro registry IX a IY.
5.8.7. Příkazy CALL
Příkaz CALL je obdobou příkazu GOSUB v BASICu. Je jím vyvolán
podprogram, který je zakončen příkazem RETURN. Přitom existují
právě tak jako u skoků podmíněných a nepodmíněných příkazy CALL,
jako například CALL Z,3000H. Zde je vyvolán podprogram na
adrese 3000H. když je nastaven Z-flag. K příkazu CALL patří také příkaz RET, který může být též
podmíněný nebo nepodmíněný. Například RET C skáče zpět, když je
nastaven indikátor přenosu.
5.8.8. Příkaz DJNZ
Speciální příkaz skoku je příkaz DJNZ, který provádí funkci
příkazu cyklu. Přitom registr B používá jako počítač smyček.
Příkaz DJNZ je spojen s relativní adresou skoku a s odpočítáváním
B registru. To může znít velmi složité, ale složité to není.
1200 06 06 LD B,06H
1202 CD 3E 00 CALL 003EH nechá zaznít tón
1205 10 FB DJNZ 1202H
1207 C3 AD 00 JP 00ADH skok do monitoru
Když se tento program odstartuje z monitoru pomocí J 1200,
zazní 6x tón, protože jsem na začátku uložili do registru B
hodnotu 6H, potom jsme standardním programem 003EH zavolali
standardní tónový program. Nyní čítač programu narazil na příkaz
DJNZ, přičemž od B registru odečte jednotku. B registr obsahuje
nyní 5H. Protože tento registr neobsahuje 0, řízení programu
skočí na 1202 a znovu se vyvolá tón. Po šesti kolech je B registr
0, takže se již neskáče na adresu 1202, ale pokračuje dále v
programu. Pomocí tohoto příkazu se vytvoří smyčka.
Program v BASICu by zněl takto:
FOR T=1 TO 6:USR ($003E):NEXT
5.8.9. Příkazy IN a OUT
Tyto příkazy vysílají a přijímají data přes porty. Tím je
umožněno provozování externích zařízení jako floppy, tiskárny
apod. Vhodným programováním se dají například řídit signály
modelů vlaků a mnoho jiných. U MZ-800 mají příkazy OUT a IN často
za úlohu provádět řízení přídavné paměti, čili aktivovat nebo
deaktivovat oblasti paměti.
6.1. Doporučení
Následující příkaz programů jsou napsány tak, že mohou být
spuštěny pomocí monitoru MZ-800. Ale pro porozumění je potřeba
Disassembler, protože pouze z hexadecimálních čísel se dá těžko
vyčíst smysl. Napsané programy se dají spustit z monitoru příkazem J 1200 a
vkládat příkazem M. Na to se musí zadat i hexadecimální
kód. Po provedení programu se řízení předá zpět do monitoru.
Pomocí Disassembleru se dá snadno rozluštit obsah programu.
6.2. Jak tisknout ve strojovém jazyce
6.2.1. Vytisknutí textu na displej
Při tisknutí ve strojovém jazyce je nejpříjemnější, dá-li se
použít standardní program monitoru. To se musí text, který
chceme vytisknout, napsat na určitou adresu v paměti. Pomocí
příkazu M napíšeme na adresu 2000H náš text, například BBG
M 2000 (CR)
42 (CR) B v ASCII kódu
42 (CR) B
47 (CR) G
0D (CR) konec textu
Jak vidíte, musí být text, který chceme vytisknout, ukončen
ODH. Nyní ještě program, který tento text vytiskne:
1200 11 00 20 LD DE,2000H adresa, textu
1203 CD 15 00 CALL 0015H vyvolání tisku
1206 C3 AD 00 JP 00ADH skok do monitoru
Takže se nejprve do DE registru nahraje adresa 2000H, na které je
text, který chceme vytisknout. Když zavoláme podprogram 0015H,
objeví se text na obrazovce. Po provedení J1200 se tedy objevy
text BBG na obrazovce.
6.2.2. Vytištění jednoho znaku
V popsaném příkladě jsme tiskli na obrazovku libovolně dlouhý
text. Nyní chceme na obrazovku vytisknout je jeden znak. Přirozeně
pro to můžeme použít výše uvedený program, ale je jednodušší
možnost, použit standardní program monitoru 0012H (viz. též
standardní programy monitoru). Znak, který má být vytištěn musí být v
akumulátoru, než je tiskový příkaz zavolán. Například:
chceme-li vytisknou 0. Na to musíme znát hodnotu v ASCII kódu a
tu uložit do akumulátoru (ASCII kód 0 je 30H).
1200 3E 30 LD A,30H vložení 0 (30H)
1202 CD 12 00 CALL 0012H tisk
1205 C3 AD 00 JP 00ADH skok do monitoru
6.3.1. GET ve strojovém jazyce
Rovněž velmi důležitou součástí programu je testování
klávesnice. V monitoru je již testování klávesnice definováno
(program monitoru 001BH). Tento program je volán stisknutím
klávesy, její hodnota je uložena v akumulátoru. Nebyla-li
stisknuta žádná klávesa, je v akumulátoru 00H. Tento program
zároveň vytiskne znak stisknuté klávesy na obrazovku.
1200 CD 1B 00 CALL 001BH GET program
1203 28 FB JR Z,1200H není stisknuta
1205 CD 12 00 CALL 0012H tisk stisk.klávesy
1208 C3 00 12 JP 1200H testování kláves.
Jestliže nyní stiskneme libovolnou klávesu, zobrazí se znak
klávesy obrazovce, Tento program se musí přerušit pomocí RESET.
6.3.2 INPUT ve strojovém jazyce
Zde jde jako v BASICu o to, zpracovávat celý řetězec znaků.
Tento program je uložen v monitoru 0003H. Program uloží celý
textový řetězec v ASCII kódu na adrese definovanou registrem DE.
Konec řetězce je automaticky ukončen 0DH.
1200 11 00 20 LD DE,2000H oblast textu
1203 CD 03 00 CALL 0003H progr. INPUT
1206 CD 06 00 CALL 0006H nový řádek
1209 CD 15 00 CALL 0015H tisk textu 120C C3 AD 00 JP 00ADH
skok do monitoru
To je program, který přečte text, uloží ho od adresy 2000H a
potom text vytiskne ještě jednou na obrazovku (J 1200). Text si
můžeme prohlédnout příkazem monitoru D.
6.3.3. Kurzorový vstup ve strojovém jazyce
Další možnost vstupu znaku z klávesnice je pomocí programu
monitoru 09B3H. Při vyvolání tohoto programu bliká korsor na
obrazovce a čeká na vklad znaku z klávesnice. Jestliže je
stisknuta klávesa, je hodnota této klávesy ve video kódu v
akumulátoru.
1200 CD B3 09 CALL 09B3H vyzvedne znak
1203 32 00 D0 LD (D000H),A umístní znak
1206 C3 AD 00 JP 00ADH skok do monitoru
Tento program vyzvedne znak z klávesnice a uloží ho na adresu
D000H. Tato adresa patří video-paměti a je to první adresa v této
paměti. Zda se tedy objeví na obrazovce vlevo nahoře.
6.4. Dimenzování ve strojovém jazyce
Nejpozději při ukládání dat do paměti potřebuje každý
programátor pole. V BASICu se pro to používá příkaz DIM, ve
strojovém jazyce si takový program musíme sami napsat. Nyní
provedeme jednoduché dimenzování pole ve strojovém jazyce a
porovnáme ho s BASICem. Nejprve příklad v BASICu:
10 DIM A(4)
20 A(0)=10000:A(1)=10001:A(2)=10003:A(3)=10005:A(4)=0
30 X=1:PRINT A(X)
Tento program by nám vytiskl na obrazovku číslo 10001. Naše data
musíme v paměti ukládat od definované adresy a to ne v dekadickém
systému, ale jako hexadecimální data. Uložíme našich pět dat za
adresu 3000H. Dá se říci, že začátek tabulky téměř odpovídá jménu
proměnné. Jestliže bychom zvolili jiný začátek, dosáhli bychom
samozřejmě jiných hodnot.
Za adresou 3000H v paměti musí být následující hodnoty
(překontrolujte pomocí příkazu D monitoru):
D3000
3000 10 27 11 27 13 27 15 27
3008 00 00
To jsou hexadecimální hodnoty A(0) - A(4). Nyní potřebujeme dva
parametry
a) naši proměnnou (zde adresa 3000H)
b) naše X (příklad v Basicu)
Jestliže první parametr máme 3000H a druhý parametr 1H, měla by
nám být vydána hodnota 2711H (10001 dek.), jako příklad v BASICu.
1200 3E 01 LD A,01H v Basicu X=1
1202 21 00 30 LD HL,3000H začátek dat
1205 87 ADD A když 16 bit A*2
1206 06 00 LD B,06H uložení hodoty z
1208 4F LD C,A akum. do BC reg.
1209 09 ADD HL,BC
120A 5E LD E,(HL)
120B 23 INC HL
120C 56 LD D,(HL)
120D EB EX DE,HL
120E CD BA 03 CALL 03BAH tiskne hodnotu HL
1211 C3 AD 00 JP 00ADH skok
do monitoru
Jestliže nyní vložíme J1200, tak se na obrazovce objeví číslo
2711H. Nyní změníme adresu na 1201H, která odpovídá našemu X.
Jestliže napíšeme 0, dostaneme 2710H (10000 dek.). Uvnitř tohoto programu jsou části, které můžeme často použít
jako užitečné programy. Podívejme se na program ještě jednou.
Nejprve máme vstupy obou parametrů. potom. Potom provedeme
ADD,A proč ? Zcela jednoduše, jestliže máme 1 jako první parametr
a 3000H jako druhý parametr, pak adresa, na které je naše hodnota,
musí být 3002H, protože máme dvou bytové hodnoty. Čili musíme A
zdvojnásobit, pomocí ADD A. Potom musíme tuto novou hodnotu
akumulátoru přičíst k našemu začátku tabulky (začátek tabulky
je 3000H), což musí dát 3002H. Potřebujeme tedy jen program, který
sčítá HL a akumulátor (ADD HL,A).
2000 C5 PUSH BC zabraň BC, nutné
2001 06 00 LD B,00H vlož do BC
2003 4F LD C,A akumulátor
2004 09 ADD HL,BC
2005 C1 POP BC vrať BC
2006 C9 RET
Nyní chybí program, který z této adresy, která je v HL, uloží
16-ti bitovou hodnotu do registru HL, čili ulož do HL obsah adresy
z HL (LD HL,(HL)).
2007 D5 PUSH DE zabraň DE, nutné
2008 5E LD E,(HL)
2009 23 INC HL
200A 56 LD D,(HL)
200B EB EX DE,HL
200C D1 POP DE
200D C9 RET
Nyní můžeme program napsat ještě jednou s použitím podprogramu.
1200 3E 01 LD A,01H
1202 21 00 30 LD HL,3000H
1205 87 ADD A
1206 CD 00 20 CALL 2000H ADD HL,A
1209 CD 07 20 CALL 2007H LD HL,(HL)
120C CD BA 03 CALL 03BAH tisk na obrazovku
1210 C3 AD 00 JP 00ADH skok do monitoru
Program můžeme odstartovat opět pomocí J1200, měnit adresu 1201H.
6.5. Smyčky
Smyčky jsou při vytváření programu velice důležitá věc, ale
při smyčkových proměnných, které jsou větší než 255, není možno
použít příkaz DJNZ. Zde se musí zhotovit nová smyčka. Napíšeme si
program, který nechá 1000 x zaznít tón (prosím raději nezkoušet,
chudák reproduktor).
1200 01 E8 03 LD BC,03E8H uloží do BC 1000
1203 C5 POSH BC zajistí BC
1204 CD 3E 00 CALL 003EH zazní tón
1207 C1 POP BC
1208 0B DEC BC
1209 78 LD A,B
120A B1 OR C
120B C2 03 12 JP NZ,1203H
120E C3 AD 00 JP 00ADH skok do monitoru
Jak vidíte, registr BC je použit jako čítač smyček. Proto musí být
tato hodnota zajištěna pomocí PUSH BC, pro případ, že by registr
BC byl změněn uvnitř smyčky. Po provedení standardního programu,
ležícího ve smyčce (zde 003EH),musí být hodnota BC opět zajištěna.
Potom musí být počet smyček sníženo jednu a musí být zjištěno, zda
již není nulový, protože v tom případě by byl program přerušen.
Zjištění, zda registr BC je nulový se provádí kombinací LD A,B a
OR C. Vzpomeňme si, že pokud jsou obě části 0, je výsledek 0.
Takže pouze pokud jsou nulové oba registry B i C, je nastaven
Z-flag. Potom je smyčka přerušena, jinak se pokračuje v jejím
provádění.
6.6. Dvojkový výraz v akumulátoru
Zde je krátký příklad programu, který vytiskne obsah akumulátoru na obrazovku jako 8-místné dvojkové číslo. Dá se použít
jako podprogram.
2000 C5 PUSH BC
2001 F5 PUSH AF
2002 06 08 LD B,08H
2004 07 RLCA
2005 F5 PUSH AF
2006 3E 30 LD A,30H
2008 30 01 JR NC,200B
200A 3C INC A
200B CD 12 00 CALL 0012H
200E F1 POP AF
200F 10 F3 DJNZ 2004
2011 F1 POP AF
2012 C1 POP BC
2013 C9 RET
Základní myšlenka programu je v tom, že obsah akumulátoru je otáčen pomocí indikátoru přenosu. PO každé rotaci je indikátor
přenosu nastaven nebo ne, podle toho co obsahuje 7-mí bit s
akumulátoru. Jestliže je idikátor přenosu nastaven, vytiskne se
1, je-li nulový, vytiskne se 0.
6.7. Převod hexadecimálního čísla na
dekadické
Pomocí tohoto programu se obsah registru HL objeví na obrazovce dekadické číslo.
1200 A7 AND A
1201 ED 52 SBC HL,DE dělení mocninou 10
1203 38 04 JR C,1209H
1205 3C INC A
1206 10 F8 DJNZ 1200H
1208 C9 RET
1209 19 ADD HL,DE při přenosu korigovat
120A C9 RET
120B C5 PUSH BC DE = BC
120C D1 POP DE
120D AF PUSH AF
120E C9 RET
120F 00 NOP
1210 CD 0B 12 CALL 120BH
1213 06 0A LD B,0AH
1215 CD 00 12 CALL 1200H program dělení
1218 C6 30 ADD 30H převod do ASCII
121A C3 12 00 JP 0012H vytisknutí
121D 01 10 27 LD BC,2710H 10000 dekadicky
1220 CD 10 12 CALL 1210H
1223 01 E8 03 LD BC,03E8H 1000 dekadicky
1226 CD 10 12 CALL 1210H
1229 01 64 00 LD BC,0064H 100 dekadicky
122C CD 10 12 CALL 1210H
122F 01 0A 00 LD BC,000AH 10 dekadicky
1232 CD 10 12 CALL 1210H
1235 01 01 00 LD BC,0001 1 dekadicky
1238 C3 10 12 JP 1210H
Když chceme tento program otestovat, např. chceme znát dekadickou hodnotu
hexadecimálního čísla C000H, musíme napsat
2000 21 00 C0 LD HL,C000H
2003 CD 1D 12 CALL 121DH
2006 C3 AD 00 JP 00ADH
Provedeme-li příkaz J 2000 se na obrazovce objeví číslo 49152. Nyní musíme jen
uložit hexadecimální číslo na adresu 2001H, spustit program a dostaneme
příslušné decimální číslo. Ještě něco k porozumění programu. Dělíme naše číslo
příslušnými mocninami deseti tak dlouho, dokud nevznikne přenos, čili nejprve
10000. Ve 43243 je obsaženo 4x, vytiskne se 4, zbytek dělíme 1000 atd.
6.8. Převod dekadického čísla na
hexadecimální
Napíšeme krátký program, který vyzvedne pětimístné dekadické číslo s klávesnice
a převede ho na hexadecimální
1200 CD B3 09 CALL 09B3H vyzvedne číslo
1203 CD CE 0B CALL 0BCEH video kód na ASCII
1206 F5 PUSH AF zachraň vlož.číslo
1207 CD 12 00 CALL 0012H tisk čísla
120A F1 POP AF vyzvedne číslo
120B D6 30 SUB 30H převádí na hexa.
120D 47 LD B,A nastav. smyček
120E B7 OR A je číslo nula (0)
120F C8 RET Z když ano, pak zpět
1210 19 ADD HL,DE přečte mocninu
1211 10 FD DJNZ 1210H
1213 C9 RET
1214 CD 06 00 CALL 0006H posun řádky
1217 21 00 00 LD HL,0000H inicializace HL
121A 11 10 27 LD DE,2710H
121D CD 00 12 CALL 1200H vyvolání výpočtu
1220 11 E8 03 LD DE,03E8H 1000 dekadicky
1223 CD 00 12 CALL 1200H
1226 11 64 00 LD DE,0064H 100 dekadicky
1229 CD 00 12 CALL 1200H
122C 11 0A 00 LD DE,000A 10 dekadicky
122F CD 00 12 CALL 1200H
1232 11 01 00 LD DE,0001H 1 dekadicky
1235 CD 00 12 CALL 1200H
1238 CD 06 00 CALL 0006H
posun řádky
123B CD BA 03 CALL 03BAH tisk obsahu HL
123E C3 AD 00 JP 00AD skok do monitoru
Tento program ze dá volat z monitoru příkazem J 1214. Zadané dekadické číslo se
převede na hexadecimální. Ještě něco k porozumění. Při pětimístném čílse, např.
45225 se mohou jednotlivé mocniny deseti nasčítat, takže principiálně se sčítání
provádí podle následujícího schématu.
45225 = 4*10000 + 5*1000 + 2*100 + 2*10 + 5*1
6.9 Přídavné příkazy Z-80
Přídavné příkazy Z-80 je něco, o čem není zmínka v žádné literatuře o Z-80.
Rozsah příkazů procesoru zahrnuje totiž asi 1000 příkazů, místo známých 400. Z
největší části se přitom jedná o příkazy, pro řízení registrů HX, HY, LX a LY.
Jak jsme se již zmínili, jedná se přitom o 8-mi bitové registry a to vždy o
vyšší a nižší byt registru IX a IY. Přitom je opcode přikloněn ke kódům registrů
H a L, právě tak jako IX a IY, právě tak jako IX, IY jsou přikloněny k opcode
registru HL.
2000 26 77 LD H,77H
2002 DD 26 77 LD HX,77H
Takže se jednoduše napíše DD nebo ED a už je možnost výběru z obrovské palety
příkazů. Musíme si dát pozor, protože téměř žádný Disassembler není schopen tyto
příkazy přečíst, protože není schopen tyto příkazy přečíst, protože o nich není
nikde zmínka. V naší nabídce naleznete Disassembler, který je schopen tyto
příkazy přeložit.