str.21 ---------------------------------------- |Binárně |Hex |Dec |ASCII |MZ-800 | |----------|-----|-----|------|--------| |01000000 |40 |64 |@ |@ | |01000001 |41 |65 |A |A | |01000010 |42 |66 |B |B | |01000011 |43 |67 |C |C | |01000100 |44 |68 |D |D | |01000101 |45 |69 |E |E | |01000110 |46 |70 |F |F | |01000111 |47 |71 |G |G | |01001000 |48 |72 |H |H | |01001001 |49 |73 |I |I | |01001010 |4A |74 |J |J | |01001011 |4B |75 |K |K | |01001100 |4C |76 |L |L | |01001101 |4D |77 |M |M | |01001110 |4E |78 |N |N | |01001111 |4F |79 |O |O | |--------------------------------------| |01010000 |50 |80 |P |P | |01010001 |51 |81 |Q |Q | |01010010 |52 |82 |R |R | |01010011 |53 |83 |S |S | |01010100 |54 |84 |T |T | |01010101 |55 |85 |U |U | |01010110 |56 |86 |V |V | |01010111 |57 |87 |W |W | |01011000 |58 |88 |X |X | |01011001 |59 |89 |Y |Y | |01011010 |5A |90 |Z |Z | |01011011 |5B |91 |[ |[ | |01011100 |5C |92 |\ |\ | |01011101 |5D |93 |] |] | |01011110 |5E |94 |^ |^ | |01011111 |5F |95 |- |- | ---------------------------------------- ---------------------------------------- |Binárně |Hex |Dec |ASCII |MZ-800 | |----------|-----|-----|------|--------| |01100000 |60 |96 |` | viz | |01100001 |61 |97 |a |dodatek | |01100010 |62 |98 |b | A | |01100011 |63 |99 |c | | |01100100 |64 |100 |d | | |01100101 |65 |101 |e | | |01100110 |66 |102 |f | | |01100111 |67 |103 |g | | |01101000 |68 |104 |h | | |01101001 |69 |105 |i | | |01101010 |6A |106 |j | | |01101011 |6B |107 |k | | |01101100 |6C |108 |l | | |01101101 |6D |109 |m | | |01101110 |6E |110 |n | | |01101111 |6F |111 |o | | ---------------------------------------| str.22 |--------------------------------------| |01110000 |70 |112 |p | viz | |01110001 |71 |113 |q |dodatek | |01110010 |72 |114 |r | A | |01110011 |73 |115 |s | | |01110100 |74 |116 |t | | |01110101 |75 |117 |u | | |01110110 |76 |118 |v | | |01110111 |77 |119 |w | | |01111000 |78 |120 |x | | |01111001 |79 |121 |y | | |01111010 |7A |122 |z | | |01111011 |7B |123 |{ | | |01111100 |7C |124 || | | |01111101 |7D |125 |} | | |01111110 |7E |126 |~ | | |01111111 |7F |127 |DEL | | ---------------------------------------- Pomocí hexmonitoru z učebního learn souboru můžete ukládání textů okamžitě vyzkoušet. Příklad: Pohybujte kursorem až do okénka hexmonitoru. Zadejte pomocí adresu A=8000 Na vstup dávejte TEST následováno V okénku najděte teď. ---------------------------------- |8000 : T 54 | |8001 : E 45 | |8002 : S 53 | |8003 : T 54 | |8004 : . 00 | |8005 : . 00 | |8006 : . 00 | |8007 : . 00 | ---------------------------------- Text TEST je nyní uložen do paměti. Hodnoty, které vlastní každé písmeno v ASCII najdete vedle písmena. 3.2 Císlice, texty a programy BASIC ----------------------------------- Jak jste viděli, lze tedy v jedné paměťové buňce jen jediný znak textu v kódu ASCII. Stejně tak lze ukládat jednoduchá dvojková čísla mezi 0 a 255. Při tom nutno je si uvědomit, že jsou různé možnosti, jak znázornit čísla. Můžete čísla ukládat jako text tím, že použijete pro cifry 0-9 znaky ASCII. Právě tak lze ukládat čísla jako binární hodnoty. str.23 Příklad: Vyjádření čísla 27 (desítkově) Dvojková hodnota znázorněna šestnáctkově 18 ASCII kód pro 2 a 7 3237 Ve znázorňování čísel existují ještě další možnosti. V dodatku A některé z nich najdete. Kódování je umění s cílem umístit co nejvíce informací do pokud možno nejmenšího prostoru v paměti, přičemž úsilí pro jejich zpětné získání má být co nejmenší. Programy BASIC se např. ukládají jako pestrá směs znaků ASCII, číslic ve dvojkové soustavě a tzv. Tokenů. U Tokenů se jedná o speciální kódy pro typická slova BASIC, jako GOTO, PRINT atd. Protože tím, že tato slova nejsou v paměti vypsána v ASCII kódu, nýbrž speciálním kódem uspoří se tak prostor v paměti. 3.3 Strojvý program. OP kódy a dvojkvá čísla Právě jako v programu BASIC mohou se ukládat i strojové programy do paměti. Na místo Tokenů BASIC se používají pro povely speciální kódy tzv. OP-kódy (operatien codes). Příklad: Odpovídající povel příkazu BASIC GOTO 1000 je ve strjové řeči JP 1000 pro JUMP (skoč) na adresu 1000. Právě tak jako u GOTO pokračuje program na jiném místě. Příkaz, JP 1000 vyžaduje však 3 Byty a je zachycen v paměti takto: první řádek: C3 OP kód: JP druhý řádek: 00 adresa: L-Byte třetí řádek: 10 adresa: H-Byte S příkazy ve strojovém jazyku jeho OP kódem a nutnými údaji adresy se v následujícím budeme blíže zabývat. Zde šlo pouze o to, ukázat, že zcela odlišné věci se mohou ukládat do paměti, i když se vlastně ukládají pouze dvojková čísla. KAPITOLA 4 Strojový jazyk: První přehled ----------------------------- V tomto odstavci přicházíme k jádru věci. Předkládáme vám první přehled o programování ve strojovém jazyce a podnikneme hned první zkušební krůčky. K tomu je potřeba se přesněji zaměřit na CPU , což znamená, že se na chvíli musíme zabývat suchou teorií. 4.1 CPU: Srdce všeho Srdce každého počítače je CPU (Central Processing Unit) ústřední procesorová jednotka, která provádí téměř všechny operace v počítači. Sám od sebe však CPU nedělá nic. Potřebuje detaijlované příkazy, co má vykonat, a to dostane ze strojového programu. Na štěstí obsahuje ROM vašeho počítače již několi tisíc příkazů ve strojovém jazyku pro CPU, protože jinak byste po zapnutí počítače nemohli nic vložit, načež nechat proběhnout program. CPU vašeho počítače je výkonný 8mi Bitový mikroprocesor Z 80 vyvinutý fy Zilog, je nástupcem Intel 8080, a obsahuje jeho kompletní povelovou sadu jakož i bezpočet přídavných funkcí. Jak vypadá CPU? Především obsahuje Z 80 jako každý CPU řadu interních paměťových buněk tzv. registry. Tyto interní paměťové buňky mají též svoje zvláštní pojmenování: A, F, BC, BE, HL, IX, IY, SP, PC. Budeme se teď zabývat významy těchto registrů. str.24 Přehled: A 8mi bitový akumulátor F 8mi bitový Flagregistr s příznaky SZHP/VNC BC 16ti bitový registr BC resp. 8mi bitový pár B, C DE 16ti bitový registr DE resp. 8mi bitový pár D, E HL 16ti bitový registr HL resp. 8mi bitový pár H, L IX 16ti bitový indexový registr IY 16ti bitový indexový registr SP 16ti bitový Stack pointer PC 16ti bitový Programm counter Registry představují krátkodobou paměť CPU. Jsou používány ve strojovém programu k tomu, aby se krátkodobě zachytily data pro později prováděné operace.Typický sled příkazů ve strojovém programu by mohl vypadat takto: -zaveď registr A obsahem paměťové buňky 1000 -odečti B od A -ulož obsah A do paměťové buňky 1001 Toto odpovídá příkazům BASIC: -A = PEEK (1000) -A = A - B - POKE 1001, A Takovéto BASICové přirovnání vám budeme dávat co možná nejčastěji, protože umožňují (doufejme) snažšímu porozumnění strojových povelů. Avšak zpět k registrům. Registry se ve strojových povelech používají rozdílným způsobem. Proto si jednotlivé registry proberemel separátně. Registr A (akumulátor). Akumulační registr A má stejný objem jako paměťové buňky RAM nebo ROM, právě jeden Byte (8 Bit). Většina operací strojového jayzka se odehrává v akumulátoru přičemž se výsledek těchto operací tam ukládá. Typický sled příkazů: - zaveď do A obsah paměťové buňky 1000 (A=PEEK(1000)) - sečti 10 s obsahem A (A=A+10) - ulož obsah A (POKE 1000, A) Akumulátor je tedy ten operační registr. Nacházíme ho skoro ve všech osmibytových mikroprocesorech (8O80, 6800, 6809, 6502). Registr BC, DE, HL. Tyto registry mají objem 16 Bit (2 Byte) a mohou proto přijmout právě údaj jedné adresy (hex.0000 ... FFFF).Přesně to je také jejich nejdůležitejší funkce, při provádění mnohých strojových povelů nesou jednu paměťovou buňku s adresou, na kterou má být operace provedena. Příklad: - zaveď do A obsah paměťové bunky jejíž adresa je v registru HL (A=PEEK(HL)) - ulož obsah do paměťové buňky jejíž adresa je v registru BC POKE BC, A Protže registry BC, DE a HL přitom ukazují na pamťové buňky, nazývají se též ukazovací registr (Point register). Samozřejmě se tyto registry mohou použít jako mezipaměť, přičemž se mohou oba jednotlivé Byty u těchto dvou Bytovch registrů používat separátně.Registrový pár BC se pak skládá z dvou osmibitových registrů B a C, registr DE z D a E, registr HL z H a L. str.25 Příklad: - zaveď do A obsah registru B (A=B) - odečti od A obsah registru C (A=A-C) - ulož A do registru D (D=A) Registr HL hraje přitom zvláětní roli. Je několik příkazů podle nichž působí HL registr jako akumulátor pro 16ti Bitové hodnoty. Např. je možno jediným povelem přečíst obsah jiného 16ti Bitového registru k HL registru. Programové počítadlo PC. Programové počítadlo (Programcounter) potřebuje CPU, aby si během postupného vykovávání příkazů pamatoval, jak pokračuje strojový program dále. CPU to dělá zrovna tak jako vy, když například si krok po kroku probíráte nějaký návod k obsluze a přitom ukazováčkem spočíváte namístě, které právě studujete. Napřed je přečten pokyn, přičemž putuje ukazováček dále textem. Když je kompletní pokyn přečten, zůstává ukazováček stát a pokyn je proveden. Programové počítadlo je ukazováčkem CPU. Protože příkazy strojového programu jsou stále v paměti počítače, obsahuje programové počítadlo vždy adresu paměťové buňky při které začíná příští příkaz. Příkaz je přečten, počítadlo počítá přitom dále, až CPU naplní kompletní příkaz. Programové počítadlo pak již ukazuje na počáteční adresu příštího příkazu, zatímco čtený příkaz je převáděn CPU. Tento cyklus opakuje PU při každém příkazu. Programové počítadlo je u každého mikroprocesoru. CPU - stack. CPU - stack (stoh) je zvláště pro CPU rezervovaný obsah RAM. Během používání učebního souboru (learn paket) pokrývá rozsah adres od hex. A000 dolů. Stack používá CPU aby si zapamatoval při podprogramových pokynech (jako GOSUB a RETURN v BASICu), kde se po návratu od podprogramu bude zase pokračovat. Po každém pokynu podprogramu zůstává na stacku uložena adresa zpětného skoku. Dejme tomu, že byste si denní kancelářskou práci organizovali takto: pokaždé, jste-li přerušen při činnosti, odložte právě zpracovaný list na hromadu (stoh) a načněte nový list. Na novém listu zaznamenejte pak toto přerušení. V případě, že budete znovu přerušeni, učiňte totéž jako předtím. Pokaždé, když naopak děj byl zpracován, či přerušení bylo ukončeno vezněte si nejhořejší list ze stohu a pokračujte na jeho zpracování. To je tedy ten naposledy přerušený postup na kterém pak pokračujete. Takto lze při tomto postupu libovolně od sebe škatulkovat přerušení, jak je třeba, když při provádění jednoho přerušení přichází další přerušení, atd. Přesto se vždycky najde cesta zpátky a zpracují se všechny postupy až dokonce. Přepracovaní manažéři mívají ve zvyku čas od času příliš narostlý stoh přenést především jinam a založit nový.To šetří přáci, ale natrvalo nepřinese nic jiného, než nepříjenosti. Ne tak u CPU. Vrství list po listu, aby příležitostně zprcoval po čase všechny. V tom je velice svědomitý! Stack CPU je jako stoh organizován jako paměť Last-in-first out. Poslední odložená hodnota se odebírá opět jako první ze stohu (viz. odst. 1.2). Vyskytne-li se přerušení programu, nebo když je způsoben podprogram, CPU odkládá okamžitý program počítadla programu PC na stoh, aby při skončení podprogramu nebo přerušení jej mohl vzít opět ze stohu zpět. str.26 Stackpointer SP --------------- Pomocí Stackpointeru (stohový ukazatel) registru si CPU pamatuje až do které adresy je stack naplněn. SP obsahuje vždy adresu následující volné pozice ve Stacku. To odpovídá místu, na které byste odložili příští list. Když se ze stacku odebírá hodnota, vrací se stackpointer zase na předcházející stav. SP ukazuje tedy vždy na nejbližší volné místo nad stohem, které není nic jiného, než rezervovaný rozsah RAM. Stack a příslušný registr stackpointeru se vyskytuje u každého mikroprocesoru. Flagregistr F Šest z osmi bitů registru F-Flagy (příznaky)- obsahují informace o stavu CPU podle naposled provedených operací. Proto se někdy tento registr nazývá stavový registr. Oba nejdůležitější flagy jsou: Z Zero Flag jeli výsledek operace 0 (nula) je Z=1, jinak Z=0 C Cassy Flag nastane-li po součtu nebo odečtu přenos na další místo (viz. 1.5) Tyto flagy udávají např. výsledek porovnávacích operací. Při porovnávací operaci provede CPU jednoduše odečítání. Výsledkem je 0, jestliže obě hodnoty byly stejné. Příklad: Porovnej obsah A s obsahem B Výsledek Z=1 hodnoty jsou stejné A=B Z=0 hodnoty jsou nestejné A<>B Stav flagů lze v programu testovat pomocí podmíněných skokových příkazů. Tyto příkazy pracují dle schematu: Když Z=0 skoč k adrese ... (IF Z=0 GOTO ... ) Když C=1 skoč k adrese ... (IF C=1 GOTO ... ) Typický sled příkazů vypadá ve strojovém jazyce takto: Srovnej A s B Když Z=1 skoč k adrese ... Toto odpovídá příkazu BASIC. Pro úplnost se chceme zmínit o zbylých flagech i když je zatím nepotřebujeme. S Sign má po aritmetických povelech znaménko S=0, pozitivní, S=1 negativní H Halfcarry obsahuje po aritmetických povelech přenos z nízkohodnotového polovičního bytu na poloviční byt vyšší hodnoty (B3 po B4) str.27 P/V Parity/ má po logických povelech paritu P=0, nerovná Overflow parita, P=1 rovná parita Při aritmetických operacích s předznamenanými čísly značí V=1 přechod z rozsahu -128 ... + 127 (viz.dodatek A3). N Subtract Označuje po aritmetických povelech typ příkazu N=0 sčítání, N=1 odečítání (Použije se pro příkaz DAA). Které operace flagy ovlivňují a které ne, nutno vyčíst z popisů strojových povelů. U každého mikroprocesoru přitom platí jiná pravidla, což bohužel ztěžuje programátorovi práci. Právě při Z80 je vliv flagů částečně velice neprůhledný. Registr IX a IY --------------- Pro úpůnost by měla být zmínka o registru IX a IY. Jedná se tu o tzv. indexové registry, které jsou používány rovněž k adresování operandů. Druhá registrová sada Á',F',BC',DÉ',HL' --------------------------------------- Registry A,F,HL,BC,DE se vyskytují v Z-80 zdvojeně. Dvěma instrukcemi lze přepínat z jedné sady registru na druhou. Protože tato druhá sada registů není v jednoduchých programech potřebná, nebudeme se zde tím dále zabývat. 4.2 Jak vypadají strojové programy? ----------------------------------- Příkazy ve strojovém jazyku jsou ve srovnání s příkazy BASIC relativně primitivní, zato však jsou podstatně rychleji prováděny. Zatímco BASIC zpracuje za sekundu nejvýše 100 příkazů, stačí zpracovat CPU několik 100 000 příkazů. Ale právě proto, že strojové příkazy jsou relativně primitivní, je většinou v programu zapotřebí též většího počtu povelů, aby se dosáhl tentýž výsledek, který dosáhne jediný povel BASIC. Jak jste se přesvědčili, vztahuje se většina příkazů strojového jazyka přímo k registru CPU nebo k paměťovým buňkám. Chceme-li např. sečíst obsahy dvou paměťových buněk, musíme nejprve obsah jedné buňky a výsledek znovu uložit zpět. V BASICu se postupuje komfortněji, protože lze používat proměnné a kompletní numerické výrazy. Příklad: Příkaz BASIC x=Y+Z-5 by ve strojovém jazyku byl: -zaveď do A obsahem buňky č.2(Y) -sečti buňku č.3 (Z) s A -odečti číslo 5 od A -ulož A do paměť.buňky č.1 (X) Přitom se musí samozřejmě udávat adresy paměťových buněk ztěžující okolností je, že CPU počítá hlavně s 8mi bitovými hodnotami, tzn. čísla musí u shora uvedeného příkladu být v rozsahu 0...255. Sice Z-80 nabízí ještě možnost pomocí jedné instrukce sečítat 16ti Bitové hodnoty, chceme-li ale sečítat ještě větší čísla, pak se musí v programu provádět sčítání postupně po místech s prováděním přenosu, avšak o tom až později. Přesto nejsou věci příliš obtížné, máme-li potřebné podprogramy pohromadě a mnoho problémů se dá ve strojovém jazyku řešit elegantně a efektivně. str.28 Mnemonics, Op kódy Symbolika ------------------ Příkazy strojového jazyka mají vždy určité pojmenování, tato jména nazývá symbolikou (mnemonics). Symbolické názvy jsou většinou anglické zkratky pro funkce povelů. Příklad: Symbol povelu zaveď do A obsah paměť. buňky 1000 zní LD pro zaveď (Load), úplný příkaz zní LD A,(1000). Seznam všech symbolů Z-80 CPU najdete v dodatku B2. Kromě symbolu se v úplném příkaze udávají jeden nebo dva operandy, s kterými se má příkaz provést. Příklad: V příkaze LD A,(1000) jsou operandy A a paměťová buňka s adresou 1000. Symbolická forma příkazů má však programátorovi jenom pomoci. Ukládány jsou jednotlivé příkazy strojového programu v podobě číselného kódu, tj.v paměti není název příkazu, nýbrž kód, tzv. OP-kód (operation code). Přklad: příkaz LD A,B Cp Code 78 příkaz LD A(1000) Op Code 3A 00 10 Vidíte, že Op-kódy příkazů mají různé délky, první příkaz vyžaduje 1 Byte, druhý zato 3 Byte. Pozoruhodné je, že u dr uhého příkazu se píše napřed Low-Byte (00) a potom High-Byte (10) v adrese (toto je obvyklé i u jiných procesorů např.8080, 6502). V dodatku C najdete Op kódy pro všechny příkazy strojového jazyka. 4.3.Zavedení a test strojových programů --------------------------------------- Pomocí Line Assembleru z učebního souboru (nejdelší okénko programovacího vidu) můžete zadávat strojové programy přímo formou symboliky. Assembler přebírá pak převod do Op-kódu a ukládá upravený strojový program do RAMu. Nemáte-li k dispozici Assembler, musíte sami překládat strojové programy do Op-kódů, a pak kódy zavést. Obvykle se to děje pak pomocí příkazu BASIC POKE. První strojový program ---------------------- Abychom si mohli vyzkoušet zavedení a testování strojového programu dejme si jednoduchý příklad: Do registrů A,B,C... se po řadě mají zadat čísla 11,22,33...77. K tomu se použiijí zadávací povely, jak již znáte. Číslo, které se má dát do registru se přitom bezprostředně zadává. str.29 Program vypadá v mnemotechnické formě takto: Příkaz Působnost LD A,11 A=11 LD B,22 B=22 LD C,33 C=33 LD D,44 D=44 LD E,55 E=55 LD H,66 H=66 LD L,77 L=77 RET RETURN Na konci tohoto programu je příkaz RET (RETURN). Tento je nutný u všech programů, které byly vyvolány učebním programem nebo z BASICu. Příkaz RET obstarává návrat k vyvolanému programu. Jestliže chybí rozloučí se s vámi váš počítač ve strojovém programu natrvalo. Když proberete tabulku příkazů v dodatku C najdete v zaváděcích příkazech programu následující Op-kódy: Příkaz (mnemonicky)Op-Kode (hex) LD A,11 3E 11 LD B,22 06 22 LD C,33 0E 33 LD D,44 16 44 LD E,55 1E 55 LD H,66 26 66 LD L,77 2E 77 RET C9 Díky Assembleru nepotřebujete tento překlad do Op-kódu provádět sami, to provede assembler za vás. Tak zavedete program: V programovacím vidu uveďte kurzor pomocí do nejspodnějšího okénka. Teď zvolte adresu 8000 (klávesa ). Vedle příkazu assembleru, který tam již je, můžete teď zavést LD A,11. Na to zadáváte ostatní příkazy. Po dokončení odjeďte kurzorem opět do monitorového okénka. Teď můžete přezkoušet, zda v rozsahu adres 8000...800E je všechno správně přeloženo do Op-kódů. Nechte si ještě jednou ukázat pro kontrolu kód odassemblovaný, protože kód musí přesně souhlasit. Jinak udělá CPU některé nedefinovatelné věci a může nastat zhroucení počítače. Pro odassemblování volte zaváděcí adresu 8000 a nechte si zobrazit pomocí program řádek po řádku. Potom, co jste zkontrolovali příkazy, můžete program vyzkoušet. Přitom je Tracer (sledovač-stopovač) právě tou správnou pomůckou se kterou lze odehrávat pochody zpomaleně a přitom sledovat co se děje. str.30 Test strojového programu ------------------------ Pomocí zkušebního vidu učebního souboru můžete nahlédnout do všech registrů CPU. Protože je kromě toho možné nechat odehrát strojový program způsobem jednotlivých kroků, můžete se po provedení každého jednotlivého příkazu přesvědčit, co se stalo. Přepojte pomocí na zkušební vid (testmodus). Teď vypadá obrazovka takto: ----------------------------------------- | 0 | ---Kalkulator |---------------------------------------| | 8000: 3E 11 06 22 0E 33 16 44 >..".3.D| ---Dump | 8008: 1E 55 26 66 2E 77 C9 00 .U&.....| |---------------------------------------| | 8000: LD A,11 | ---Disassembler | 8001: LD B,22 | |---------------------------------------| | A: BC: DE: HL: F:SZ-H-PNC | ---CPU | 00 0000 0000 0000 00000000 | | | | IX: IY: PC: SP: | | 0000 0000 8000 A000 | |---------------------------------------| | * # | ---Příkazové okénko ----------------------------------------- Aby bylo možno startovat nějaký program, musíte napřed zavést do programového počítadla PC startovací adresu strojového programu.To v tomto případě není však vůbec nutné, jelikož PC již obsahuje startovací adresu našeho strojového programu 8000. Povelem Trace můžete nechat probíhat program po jednotlivých krocích, stisknete klávesu a objeví se na indikaci: ----------------------------------------- | * T : # | ----------------------------------------- Když teď aktivujete <šipka dolů> bude proveden první příkaz programu. Stlačíte-li znovu <šipka dolů> provede se další příkaz. Přitom označuje ukazatel stavu T vpravo v okénku, že byl startován strojový program. Dáte-li dvakrát <šipka dolů> uvidíte na stínítku toto: ----------------------------------------- | 0 | |---------------------------------------| | 8000: 3E 11 06 22 0E 33 16 44 >..".3.D| | 8008: 1E 55 26 66 2E 77 C9 00 .U&.....| |---------------------------------------| | 8004: LD C,33 | | 8006: LD D,44 | |---------------------------------------| | A: BC: DE: HL: F: SZ-H-PNC | | 11 2200 0000 0000 00000000 | | | | IX: IY: PC: SP: | | 0000 0000 8004 9FFE | |---------------------------------------| | * # T | ----------------------------------------- str.31 Hodnota pod PC je okamžitým stavem programového počítadla PC. Udává adresu v pořadí příštího příkazu programu. Nahoře v disassembleru vidíte, který příkaz to je, totiž LD C,33. Oba první příkazy LD A,11 a LD B,22, jsou tedy již provedeny. Pohlédnete-li na okénko CPU, zjistíte, že všechno fungovalo: Do A je zavedeno 11, do B 22. Příští povely programu můžete nechat provést pomocí <šipka dolů> a přitom uvidíte, jak počítadlo programu počítá dále a jak se postupně registry plní danými hodnotami. V obou polích vpravo u okénka CPU se jedná vlastně o Flagregistr F a o Stackpointer SP. Když byl program zcela odehrán, zhasne T - flag v příkazovém okénku a PC ukáže zase 8000. Teď vidíte v okénku CPU, že všechny registry byly naplněny danými hodnotami. ----------------------------------------- | A: BC: DE: HL: F: SZ-H-PNC | | 11 2233 4455 6677 00000000 | | | | IX: IY: PC: SP: | | 0000 0000 8000 A000 | ----------------------------------------- Potom, co jste si vyzkoušeli program ve strojovém jazyce, doufáme, že vás můžeme zase zatížit trochou teorie. 4.4 Kterým příkazům rozumí CPU? ------------------------------- Že podle příkazů ve strojové řeči se operuje jednotlivými registry nebo buňkami to už víte. O operacích, které jsou přitom možné, chceme vám dát krátký přehled. Detaily budou teprve látkou příští kapitoly, celkový přehled všech povelů najdete v dodatku C. Povely k nabírání ----------------- Těmito povely se transferují data mezi registry a paměťovými buňkami. Skokové povely -------------- Těmito povely je pokračováno v programu na jiném místě. Přitom je vždy udávána adresa pod kterou je instrukce uložena a kde má být v programu pokračováno. Příklad: JP 'Jump' 'Skoč na' GOTO CALL 'Call subroutine''Podprogramový skok na' GOSUB RET 'Return' 'Návrat' RETURN Jestliže CPU se setká v některém podprogramu na nějaký povel RET, vrátí se tento zpět na místo, ze kterého byl podprogram vyvolán a odtud pracuje dále. Největší význam mají podmíněné skokové povely, kterými je testován (zkušen) stav některého CPU Flagu. Skok je proveden jen tehdy, když test dopadne pozitivně. str.32 Příklad: JP Z 'Jump if Z set' 'Skoč když Z je nastaven'IF Z=1 GOTO JP NZ 'Jump if Z reset''Skoč když Z je nulován' IF Z=0 GOTO Aritmetické povely ------------------ Těmito povely lze provádět jednoduché početní operace, tj. součet, odečítání, přírůstek i úbytek. U posledních se jedná o jednoduchý součet nebo odečet od 1. Příklad: ADD 'Add' 'Sečti' SUB 'Subtract' 'Odečti' INC 'Increment''Povyš o 1' DEC 'Decrement''Sniž o 1' Porovnávací povely ------------------ Porovnávacími povely se porovnávají dvě hodnoty a nastavují se příslušné flagy. Příklad: CP 'Compare' 'Porovnej' Logické povely -------------- Těmito povely se provádějí logické operace AND, OR, XOR (viz.1.6). Příklad: AND 'AND' 'Logická operace -a-' OR 'OR' 'Logická operace -nebo- XOR 'Exclusive OR' 'Logická operace -výlučné nebo- Povely k přesunu bitu --------------------- Těmito povely se přesouvají 8mi bitové hodnoty o jeden bit doprava nebo doleva. Příklad: SRA 'Shift right arithmetical' 'Přesun doprava' SLA 'Shift left arithmetical' 'Přesun doleva' Kontrolní povely CPU -------------------- Sem spadají všechny možné speciální povely jako např. nastavování a invertování invertování Carry Flagu nebo zastavení CPU. Příklady: SCF 'Set Carry flag' 'Nastav Carry flag' CCF 'Complement Carry flag' 'Invertuj Carry flag' str.33 Tím jsou rozdílné typy povelů vyčerpány. Samozřejmě se vyskytuje mezi jednotlivými rubrikami podstatně více jednotlivých povelů, zatím jsme uvedli pouze příklady. V podstatě nejsou žádné další operace v povelové sade obsaženy. Chybí, jako u téměř všech 8mi bitových mikroprocesorů např. násobení, pro které se již musí napsat malý program, ve kterém se pomocí sčítání a přesuvných operací provede násobení dvou čísel. 4.5 Druh adresování: Odkud bere CPU data ? ------------------------------------------ Různé operace strojového jazyka se provádějí pomocí dat, které udává příkaz, např. pomocí obsahu jednoho registru nebo buňky. Způsob jakým se tato data vyznačují v příkaze, označujeme druhem adresování. Podívejme se na příkaz naplň akumulátor různým způsobem podle druhu adresování. Bezprostřední adresování (Immediate Adressing) ---------------------------------------------- Tento druh adresy je třeba, když operand instrukce je číslo, které je bezprostředně udáno v příkaze: Příklad: naplň akumulátor bezrostředně 3 povel: LD A,03 Op-kód: 3E 03 Číslo 3 - operand instrukce - se tedy udává společně v kódu příkazu. Registrové adresování (Register Adressing) ------------------------------------------ Tento druh adresy je užit, když operand instrukce je CPU registr. Příklad: naplň akumulátor obsahem B registru povel: LD A,B Op-kód: 78 Přímé resp. absolutní adresování (Extendet Adressing) ----------------------------------------------------- Tento druh adresy se užívá, když operand instrukce je paměťová buňka, jejíž adresa je udána přímo v příkaze. Příklad: naplň akumulátor obsahem paměť.buňky 8100 povel: LD A,(8100) Op-kód: 3A 0081 Adresa 8100 se dává do závorek, aby bylo jasné, že se jedná o obsah paměťové buňky. str.34 Nepřímé registrové adresování (Register Indirect Adressing) ----------------------------------------------------------- Tento druh adresy se užívá, když operand instrukce je paměťová buňka, jejiž adresa stojí v BC-, DE- nebo HL registru. Příklad: naplň do A obsah paměť.buňky jejíž adresa je v HL registru povel: LD A,(HL) Op-kód: 7E Aby bylo jasně znát, že je míněna paměťová buňka, jejíž adresa je v HL a ne v samotném HL registru, dává se HL do závorek. Indexované adresování (Indexed Adressing) ----------------------------------------- Tento druh adresy, podobně jako u nepřímého registrového adresování, stojí adresa v jednom z indexových registrů IX nebo IY. Příklad: naplň do A obsah 5.Bytu od adresy IX povel: LD A,(IX+05) Op-kód: DD 7E 05 Implikované adresování (Implied Adressing) ------------------------------------------ Tento druh adresy se užívá, když není udán žádný operand, protože příkaz je převeden pouze určitým operandem. Příklad: invetuj obsah akumulátoru (complement Accumulator) povel: CPL Op-kód: 2F Povel působí vždy na akumulátor, proto se tento již také neudává explicitně. Relativní adresování (Relative adressing) ----------------------------------------- Tento druh adresy se používá u většiny 8mi bitových mikroprocesorů, pouze na relativní skoky. V Op-kódu se udává adresa skoku relativní hodnotou, která se přičítá k okamžitému stavu programového počitadla. V assembleru můžete však počítat od prvního byte skokové instrukce. Příklad: skoč 5 byte vpřed povel: JR 05 (Jump relative) Op-kód: 18 03 str.35 Bitové adresování (Bit Adressing) ---------------------------------- S tímto druhem adresování se mohou bity 0...7 jednoho registru nebo paměťové buňky dávat, brát nebo se na ně dotazovat. Příklad: nastav bit 4 z C registru na 1 povel: SET 4,C Op-kód: CB E1 U jiných mikroprocesorů existují částečně ještě další druhy adresování, obzvláště nabízí 6502 velké množství možností. KAPITOLA 5 Příkazová věta : Co všechno dokáže ---------------------------------- V této kapitole se budeme zabývat blíže s příkazy strojového jazyka procesoru Z-80. Představíme vám všechny základní důležité příkazy CPU a při tom též ukážeme jak se tyto příkazy používají. Příliž speciální příkazy Z-80 v následujícím výkladu pomineme. Úplnou sbírku všech příkazů najdete v dodatku C. Příkazy vám představíme v jednotlivých skupinách. Ke každé skupině budou uvedeny základní programovací techniky a příklady. Přitom se někdy může narážet na ještě neprobrané věci, v takovém případě vždy dáme krátké vysvětlení. V případě kdy vám bude nejasná působnost toho nebo onoho příkazu, vezměte si k ruce učební soubor a můžete si příkaz vyzkoušet. V poslední kapitole jste poznali jak jednotlivým způsobem se to děje, když necháváte příkazy provádět po jednotlivých krocích. Následující programovací příklady můžete zadávat přímo v okénku assembleru. Pro kontrolu je skoro všude společně udán programový kód. Při zadávání strojových programů se má vždy postupovat s co největší pečlivostí, nepatrná chyba může hned po startu přivést computer ke 'zhroucení', v mnoha případech vám pak nic jiného nezbude, než reset (vynulování) a nové natažení "učebního programu" (learn program), protože paměť počítače se při zhroucení snadno uvede do nepořádku. 5.1 Skokové povely ------------------ Skokovými povely lze během programu přeskakovat na různá místa, vyvolávat podprogramy a vracet se opět k hlavnímu programu, způsobem odpovídajícím povelům BASIC GOTO, GOSUB a RETURN. Nepodmíněné absolutni skoky Vyvolávání podprogramu a návrat ------------------------------------------------------- | Mnemonic | Působnost | Flagy | Hexkód |Analog BASIC | |-----------------------------------------------------| | Nepodmíněné absolutní skoky | |-----------------------------------------------------| | JP nm | PC=nm | ----- | C3,m,n | GOTO nm | | JP (HL) | PC=HL | ----- | E9 | GOTO HL | | JP (IX) | PC=IX | ----- | DD,E9 | GOTO IX | | JP (IY) | PC=IY | ----- | FD,E9 | GOTO IY | |-----------------------------------------------------| str.36 | Nepodmíněné vyvolání podprogramu | |-----------------------------------------------------| | CALL nm | SP=SP-1 | ----- | CD,m,n | GOSUB nm | | | (SP)=PC^H | | | | | | SP=SP-1 | | | | | | (SP)=PC^L | | | | | | PC=nm | | | | |-----------------------------------------------------| | Nepodmíněný return | |-----------------------------------------------------| | RET | PC^L=(SP) | ----- | C9 | RETURN | | | SP=SP+1 | | | | | | PC^H=(SP) | | | | | | SP=SP+1 | | | | ------------------------------------------------------- V povelu JP (Jump, česky skoč) se prostě dává adresa cíle skoku a to adresa u které začíná Op-kód příkazu kam se má skočit. V tabulce se tato adresa vyznačuje "nm". Nutno si povšimnout, že v Op-kódu jsou H-Byte a L-Byte cíle skoku zaměněny. Následující příklad si můžete pomocí "učebního souboru" vyzkoušet tak, že zadáte příkazy na udaných adresách a pak startujete program jako bylo popsáno v poslední kapitole. Příklad: Adresa Kód Příkaz Analog BASIC 8000: C3 05 80 JP 8005 8000:GOTO 8005 8003: 06 99 LD B,99 8003:B=99 8005: 0E 99 LD C,99 8005:C=99 8007: C3 07 80 JP 8007 8007:GOTO 8007 800A: C9 RET 800A:RETURN Když jste zadali program, startujte ho "zkušebním způsobem" (Test modus) "učebního souboru" (k tomu dávejte: PC=8000, následováno <šipka dolu>). Za průběhu programu po jednotlivých krocích (klávesa <šipka dolu>) uvidíte na indikaci cestu CPU programem podle postavení programového počitadla : 8005, 8007, 8007, 8007... Podíváte-li se na registry uvidíte že pouze registr C nabral hodnotu 99, nikoliv však B, protože tento naplňovací povel byl přeskočen. Na konci uvázne program v nekonečné smyčce. Tracer však můžete kdykoliv opustit, vložením nové hodnoty do PC. Podíváte-li se znovu do shora uvedené tabulky vidíte, že povel JP ponechá všechny Flagy nezměněné (vyznačeno -----). Současně můžete na působení příkazu vidět, že se nic jiného nestalo, než že programové počitadlo PC nabralo adresu nm, která byla obsažena v příkazu. Chcete-li během programu navodit podprogram, použijte povel CALL (Call subroutine, česky volej podprogram). V povelu CALL se stejně jako u povelu JP udává adresa "nm" cíle skoku, tedy adresa startu podprogramu. Podprogram končí příkazem RET (Return, česky návrat), který způsobí návrat zpět na místo v programu, na kterém byl podprogram volán. Příklad: Adresa Kód Příkaz Analog BASIC 8000: CD 3E 00 CALL 003E 8000:GOSUB 003E 8003: 06 77 LD B,77 8003:B=77 8005: C9 RET 8005:RETURN str.37 Když budete startovat tento program, nechte ho proběhnout v jednom tahu, nikoliv krokovým způsobem. To se uskuteční následovně: Po vložení startovací adresy PC=8000 z Test modusu "učebního souboru", dejte následováno dvojnásobným . Uslyšíte pak krátký pípavý tón, protože u vyvolaného podprogramu se jedná o běžný program ROMu (ROM-routine) vašeho computeru který je vyřizován pípáním. Podíváte-li se na registry vidíte, že B je obsazen správně 77. Po podprogramu tedy pokračoval hlavní program dále. Povel RET na konci přivodí vždy návrat do programu "učebního souboru" (Learn program). V povelových tabulkách najdete přesný popis jak při vyvolání podprogramu postupuje počítač programem při odkládání na Stack (stoh). Nejprve je stackpointer snížen o 1, aby ukazoval na nejbližší volnou pozici stacku (SP=SP-1). Pak je uložen H-Byte z PC na stack. Toto je zaznamenáno (SP)=PC^H. Pak se SP znovu sníží aby bylo možno uložit PC^L na stack (SP=SP-1, (SP)=PC^L). Teprve potom je proveden skok "PC=nm". Stack tedy jde v RAMu pozpátku, protože SP se pokaždé snižuje o 1. Povel RET opět odebírá hodnoty ze stacku do počitadla programu, takže v programu se dá pokračovat. Přitom je důležité, aby na stacku uložená programová hodnota počitadla již ukazovala na příští povel, na povel CALL. To se děje automaticky, protože programové počitadlo již před provedením příkazu je jednoduše přírůstkováno. (viz 4.1) Tady to můžete pozorovat pomocí Learn programu. Pohleďte na okénko CPU a tam vidíte : ----------------------------------------- | A: BC: DE: HL: F: SZ-H-PNC | | 00 7700 0007 0000 01000100 | | | | IX: IY: PC: SP: | | 0000 0000 8000 A000 | ----------------------------------------- Když teď startujete klávesou a <šipka dolu> obsahuje SP pouze ještě hodnotu 9FFC. Jestliže pomocí přepnete do programovacího módusu a podíváte se v okénku monitoru na poslední pozici stacku obsazenou M=9FFC, najdete tam 03 a v další paměťové buňce bude 80. Přitom se jedná právě o návratovou adresu z podprogramu 8003. Podprogramy jsou pro programování ve strojovém jazyce zvlášť důležitou věcí. Každý delší program je dělen na malé porce, které jako podprogramy lze později spojovat jako hlavní program. Tyto malé podprogramy jsou testovány samostatně, takže se při spojování již ví že fungují. Zvlášť pěkná bude záležitost máme-li k dispozici assembler lako MZ-MACRO. Pak můžeme podprogramy vybavit pojmenováním, při pozdějším použití podprogramů udáváme pak pouze příslušné jméno. Tímto způsobem je možné si sestavovat svou vlastní řeč, ve které pak můžeme programovat. Povely této "řeči" jsou pak dotyčné jednotlivé podprogramy.