Obsah
1. Zobrazení čísel a zpracování příznaků mikroprocesoru Zilog Z80
2. Podprogram pro tisk celočíselné hodnoty v rozsahu 0 až 9999
3. Ukázka použití podprogramu pro tisk celého čísla
4. Výsledek pokusu o vytištění záporných čísel
5. Tisk maximální podporované hodnoty a pokus o vytištění vyšší hodnoty
7. Kombinace s dalšími subrutinami
8. Příznaky mikroprocesoru Zilog Z80
9. Seznam instrukcí, které modifikují příznakové bity
10. Zobrazení obsahu příznakového registru F po provedení vybrané operace
11. Příznakové bity po provedení celočíselné operace 1+2
12. Příznakové bity po provedení celočíselné operace 0+0
13. Příznakové bity po provedení operace 255+1
14. Příznakové bity po provedení operace 254+1
15. Příznakové bity po provedení operace 255+255
16. Příznakové bity po provedení operace 100+100
17. První shrnutí: význam příznaků C, V, S a Z
18. Příloha: upravený soubor Makefile pro překlad demonstračních příkladů
19. Repositář s demonstračními příklady
1. Zobrazení čísel a zpracování příznaků mikroprocesoru Zilog Z80
V úvodní části dnešního článku si ukážeme způsob použití standardního podprogramu (subrutiny) uloženého v paměti ROM, který slouží pro výpis celých čísel na obrazovku. Tento podprogram byl sice původně určen pro specifické účely (konkrétně pro výpis čísel řádků v Sinclair BASICu), ovšem i přes jeho některá omezení bude podpora pro výpis numerických hodnot velmi užitečná v navazující části článku.
Obrázek 1: Výpis numerických hodnot na obrazovku podprogramem uloženým v ROM.
Navíc se podrobněji zmíníme o problematice příznaků (flags), které jsou nastavovány některými instrukcemi a které lze využít jak v podmíněných skocích, tak i v dalších typech strojových instrukcí (rotacích atd). Prozatím jsme totiž používali pouze dva příznaky, a to konkrétně carry (příznak přenosu) a zero (příznak nulovosti), ovšem mikroprocesor Zilog Z80 kromě toho nabízí i další příznaky, které lze využít jak ve výpočtech s hodnotami se znaménkem, tak i při realizaci některých optimalizací.
2. Podprogram pro tisk celočíselné hodnoty v rozsahu 0 až 9999
Jak jsme si již naznačili v úvodní kapitole, popíšeme si v dnešním článku nejdříve způsob použití standardního podprogramu uloženého v paměti ROM, který dokáže vypsat hodnotu celého čísla na obrazovku a přitom posunout pomyslný (neviditelný) kurzor takovým způsobem, aby tisk dalších znaků následoval až za nově zobrazeným číslem. Tento podprogram, jenž je i s dalšími podrobnostmi popsán například na stránce https://skoolkid.github.io/rom/asm/1A1B.html, začíná na adrese 0×1A1B a očekává na vstupu celé šestnáctibitové číslo uložené v registrovém páru BC (připomeňme si, že ROM je mapována od 0×0000 do 0×3fff). Číslo předané v registrovém páru BC je vytištěno a přitom subrutina nenávratně modifikuje obsah akumulátoru A a již zmíněného registrového páru BC (a podle očekávání i příznaků). Ostatní dva registrové páry DE a HL nejsou touto subrutinou modifikovány (jsou totiž uloženy na zásobník a před koncem subrutiny jsou obnoveny).
Obrázek 2: Tento podprogram je využíván například interpretrem Sinclair BASICu pro zobrazení čísel řádků.
3. Ukázka použití podprogramu pro tisk celého čísla
Základní způsob použití výše zmíněného podprogramu je ve skutečnosti až triviální. Pouze nám postačuje smazat obrazovku (či alternativně otevřít kanál pro zápis na obrazovku – screen), vložit do registrového páru BC celočíselnou hodnotu, která se má vypsat a následně zavolat subrutinu pro tisk celého čísla. Vše lze realizovat čtyřmi (resp. jak uvidíme o odstavec dále, tak jen třemi) instrukcemi:
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld BC, 1234 ; numerická hodnota, kterou chceme vytisknout call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu end ENTRY_POINT
Způsob překladu tohoto programu do strojového kódu bude vypadat následovně:
ENTRY_POINT EQU 8000 ROM_CLS EQU 0DAF OUT_NUM_1 EQU 1A1B ORG 8000 8000: label start 8000:CDAF0D CALL 0DAF 8003:01D204 LD BC, 04D2 8006:CD1B1A CALL 1A1B 8009:C9 RET 800A: END 8000 Emiting TAP basic loader Emiting TAP from 8000 to 8009
Podívejme se na výsledek tak, jak ho uvidíme na obrazovce ZX Spectra:
Obrázek 3: Hodnota 1234 vytištěná na obrazovce ZX Spectra.
Poznámka na okraj – v případě, že program končí dvojicí instrukcí CALL + RET, můžeme program o jednu instrukci zkrátit. Je tomu tak z toho důvodu, že volaná subrutina (jakákoli) končí instrukcí RET (nebo její podmíněnou variantou), takže můžeme tuto instrukci „zneužít“ pro přímý návrat do BASICu. To konkrétně znamená, že následující dvojici řádků:
call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu
je možné nahradit za jedinou instrukci:
jp OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla + návrat
V dnešních demonstračních příkladech ovšem ponechávám delší variantu, aby bylo možné snadno a bez většího přemýšlení za volání OUT_NUM1 přidat další instrukce.
4. Výsledek pokusu o vytištění záporných čísel
Již v úvodním textu jsme si řekli, že standardní subrutina OUT_NUM1 byla původně určena pro tisk čísel řádků v Sinclair BASICu. S tím do značné míry souvisí i různá omezení, které tato subrutina má. Například nedokáže korektně vytisknout záporná čísla (to ovšem dává smysl, protože čísla řádků nemohou být záporná). O tomto omezení se můžeme velmi snadno přesvědčit překladem a spuštěním nepatrně upraveného demonstračního příkladu:
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld BC, -1234 ; numerická hodnota, kterou chceme vytisknout call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu end ENTRY_POINT
Výsledek bude vypadat následovně:
Obrázek 4: Výsledek pokusu o vytištění záporného čísla standardní subrutinou OUT_NUM1.
5. Tisk maximální podporované hodnoty a pokus o vytištění vyšší hodnoty
V Sinclair BASICu platí ještě další omezení na rozsah čísel řádků. Nejvyšší číslo řádku může mít hodnotu 9999 (což je zvláštní, protože další BASICy pro osmibitové mikropočítače mají méně umělé omezení na 32767 řádků nebo na 65535 řádků):
Obrázek 5: Program v BASICu s číslem řádku 9999.
Obrázek 6: Program v BASICu s číslem řádku 10000 je již nekorektní.
A rutina OUT_NUM1 toto omezení skutečně bere v úvahu, protože maximální celočíselná hodnota, kterou lze bez problémů vytisknout, je rovna právě 9999. Opět se o tom snadno přesvědčíme, a to překladem a spuštěním následujících dvou demonstračních příkladů. První příklad by měl vytisknout hodnotu 9999, druhý pak „pokaženou“ hodnotu 10000 (která již není podporována).
Obrázek 7: Vytištění maximální hodnoty podporované subrutinou OUT_NUM1.
Obrázek 8: Pokus o vytištění hodnoty 10000 subrutinou OUT_NUM1.
Zdrojový kód příkladu, jenž vytiskne hodnotu 9999:
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld BC, 9999 ; numerická hodnota, kterou chceme vytisknout call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu end ENTRY_POINT
Program, který se pokusí o vytištění hodnoty 10000:
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld BC, 10000 ; numerická hodnota, kterou chceme vytisknout call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu end ENTRY_POINT
6. Vytištění číselné řady
Vyzkoušejme si nyní tisk číselné řady, v níž jednotlivé hodnoty od sebe nebudou nijak odděleny. Nejprve vytiskneme číslici 1, potom ihned za ní číslici 2 atd. až do hodnoty 10. Výsledek zobrazený na obrazovce ZX Spectra by tedy měl vypadat následovně:
Obrázek 9: Celočíselné hodnoty 1, 2, … až 10 zobrazené za sebou, bez použití oddělovače.
Samozřejmě nám nic nebrání ve vložení volání subrutiny OUT_NUM1 do programové smyčky, která může mít následující strukturu:
ld BC, 1 ; numerická hodnota, kterou chceme vytisknout next_number: call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla inc C ; a zvýšit o jedničku ld A, C cp 11 ; kontrola na konec smyčky jr nz, next_number
Problém ovšem spočívá v tom, že hodnota uložená v registrovém páru BC je v subrutině OUT_NUM1 poškozena a tudíž takto navržená smyčka nebude zcela funkční. Musíme tedy před voláním subrutiny obsah BC uschovat (například na zásobník nebo do druhé sady registrů) a po návratu ze subrutiny ji obnovit:
ld BC, 1 ; numerická hodnota, kterou chceme vytisknout next_number: push BC ; uchovat počitadlo call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla pop BC ; obnovit počitadlo inc C ; a zvýšit o jedničku ld A, C cp 11 ; kontrola na konec smyčky jr nz, next_number
Takto navržená programová smyčka již bude plně funkční a můžeme ji tedy použít v demonstračním příkladu, jenž bude mít tvar:
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld BC, 1 ; numerická hodnota, kterou chceme vytisknout next_number: push BC ; uchovat počitadlo call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla pop BC ; obnovit počitadlo inc C ; a zvýšit o jedničku ld A, C cp 11 ; kontrola na konec smyčky jr nz, next_number ret ; návrat z programu do BASICu end ENTRY_POINT
Pro úplnost se podívejme, jak je tento příklad přeložen do strojového kódu. Jeho délka je rovna sedmnácti bajtům:
ENTRY_POINT EQU 8000 ROM_CLS EQU 0DAF OUT_NUM_1 EQU 1A1B ORG 8000 8000: label start 8000:CDAF0D CALL 0DAF 8003:010100 LD BC, 0001 8006: label next_number 8006:C5 PUSH BC 8007:CD1B1A CALL 1A1B 800A:C1 POP BC 800B:0C INC C 800C:79 LD A, C 800D:FE0B CP 0B 800F:20F5 JR NZ, 8006 8011:C9 RET 8012: END 8000 Emiting TAP basic loader Emiting TAP from 8000 to 8011
7. Kombinace s dalšími subrutinami
V úvodním textu jsme si řekli, že subrutina OUT_NUM1 byla navržena tak, aby ji mohl využívat přímo interpret Sinclair BASICu. Lze ji tedy zkombinovat s dalšími podprogramy určenými pro tisk textů a dalších hodnot na obrazovku ZX Spectra. Díky tomu je například možné po zobrazení celočíselné hodnoty vytisknout znak pro nový řádek subrutinou na adrese 0×10 (tu již dobře známe) a tím pádem provést odřádkování:
Obrázek 10: Hodnoty 1 až 10 vytištěné po sobě, ovšem s odřádkováním.
Aby se provedlo odřádkování, musíme programovou smyčku z předchozí kapitoly pouze rozšířit o vytištění řídicího znaku 0×0d. Podívejme se, jak úprava programu vypadá:
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld BC, 1 ; numerická hodnota, kterou chceme vytisknout next_number: push BC ; uchovat počitadlo call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ld A, 0x0d ; kód znaku pro odřádkování rst 0x10 ; zavolání rutiny v ROM pop BC ; obnovit počitadlo inc C ; a zvýšit o jedničku ld A, C cp 11 ; kontrola na konec smyčky jr nz, next_number ret ; návrat z programu do BASICu end ENTRY_POINT
Způsob překladu tohoto demonstračního příkladu do strojového kódu:
ENTRY_POINT EQU 8000 ROM_CLS EQU 0DAF OUT_NUM_1 EQU 1A1B ORG 8000 8000: label start 8000:CDAF0D CALL 0DAF 8003:010100 LD BC, 0001 8006: label next_number 8006:C5 PUSH BC 8007:CD1B1A CALL 1A1B 800A:3E0D LD A, 0D 800C:D7 RST 10 800D:C1 POP BC 800E:0C INC C 800F:79 LD A, C 8010:FE0B CP 0B 8012:20F2 JR NZ, 8006 8014:C9 RET 8015: END 8000 Emiting TAP basic loader Emiting TAP from 8000 to 8014
8. Příznaky mikroprocesoru Zilog Z80
Ve druhé části dnešního článku se budeme zabývat popisem příznaků (flags) osmibitového mikroprocesoru Zilog Z80. Jedná se o sadu šesti bitů, které jsou nastavovány mnoha strojovými instrukcemi (typicky instrukcemi aritmetickými, ale i mnoha dalšími, jak uvidíme dále) a mohou být testovány v podmíněných skocích, podmíněných skocích do podprogramů či podmíněných výskoků (návratů) z podprogramů. Všech šest příznaků je uloženo v příznakovém registru nazvaném příznačně F (od slova flags). Struktura tohoto registru vypadá následovně:
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Příznak | S | Z | x | H | y | P/V | N | C |
Jednotlivé příznakové bity mají následující význam:
Příznak | Jméno | Stručný popis |
---|---|---|
C | carry | příznak přenosu nebo výpůjčky, taktéž první nebo poslední bit u bitových posunů |
N | add/subtract | nulovaný instrukcí ADD, nastavovaný instrukcí SUB |
P/V | parity/overflow | lichá či sudá parita u logických operací, přetečení do znaménkového bitu u aritmetických operací |
y | × | |
H | half carry | přetečení ze čtvrtého do pátého bitu při provádění aritmetických operací |
x | × | |
Z | zero | příznak nulovosti výsledku |
S | sign | nejvyšší (osmý) bit výsledku, který nese informace o znaménku |
Mezi aritmetické operace pro zjednodušení počítáme i instrukci CP pro porovnání. Ta skutečně provede výpočet rozdílu, ovšem výsledek se zahodí; nastaví se pouze příznakové bity.
9. Seznam instrukcí, které modifikují příznakové bity
Na mikroprocesoru Zilog Z80 modifikuje příznakové bity mnoho strojových instrukcí. Tyto instrukce jsou vypsány v následující tabulce, přičemž je u každého příznaku uvedeno, jak se daný příznak instrukcí modifikuje. Význam symbolů použitých v této tabulce byl převzat ze stránky 80 MICROPROCESSOR Instruction Set Summary:
Symbol | Význam |
---|---|
– | příznak zůstane nezměněn |
* | příznak je instrukcí změněn (na základě provedené operace) |
0 | příznak se vynuluje |
1 | příznak se nastaví na jedničku |
? | hodnota příznaku není oficiálně specifikována |
Následuje slíbená tabulka s instrukcemi, z nichž každá nějakým způsobem modifikuje příznak či několik příznaků:
Instrukce | S | Z | H | P | N | C |
---|---|---|---|---|---|---|
ADC A,s | * | * | * | V | 0 | * |
ADC HL,ss | * | * | ? | V | 0 | * |
ADD A,s | * | * | * | V | 0 | * |
ADD HL,ss | – | – | ? | – | 0 | * |
ADD IX,pp | – | – | ? | – | 0 | * |
ADD IY,rr | – | – | ? | – | 0 | * |
AND s | * | * | * | P | 0 | 0 |
BIT b,m | ? | * | 1 | ? | 0 | – |
CCF | – | – | ? | – | 0 | * |
CP s | * | * | * | V | 1 | * |
CPD | * | * | * | * | 1 | – |
CPDR | * | * | * | * | 1 | – |
CPI | * | * | * | * | 1 | – |
CPIR | * | * | * | * | 1 | – |
CPL | – | – | 1 | – | 1 | – |
DAA | * | * | * | P | – | * |
DEC s | * | * | * | V | 1 | – |
IN r,[C] | * | * | * | P | 0 | – |
INC r | * | * | * | V | 0 | – |
INC [HL] | * | * | * | V | 0 | – |
INC [xx+d] | * | * | * | V | 0 | – |
IND | ? | * | ? | ? | 1 | – |
INDR | ? | 1 | ? | ? | 1 | – |
INI | ? | * | ? | ? | 1 | – |
INIR | ? | 1 | ? | ? | 1 | – |
LD A,i | * | * | 0 | * | 0 | – |
LDD | – | – | 0 | * | 0 | – |
LDDR | – | – | 0 | 0 | 0 | – |
LDI | – | – | 0 | * | 0 | – |
LDIR | – | – | 0 | 0 | 0 | – |
NEG | * | * | * | V | 1 | * |
OR s | * | * | * | P | 0 | 0 |
OTDR | ? | 1 | ? | ? | 1 | – |
OTIR | ? | 1 | ? | ? | 1 | – |
OUTD | ? | * | ? | ? | 1 | – |
OUTI | ? | * | ? | ? | 1 | – |
RL m | * | * | 0 | P | 0 | * |
RLA | – | – | 0 | – | 0 | * |
RLC m | * | * | 0 | P | 0 | * |
RLCA | – | – | 0 | – | 0 | * |
RLD | * | * | 0 | P | 0 | – |
RR m | * | * | 0 | P | 0 | * |
RRA | – | – | 0 | – | 0 | * |
RRC m | * | * | 0 | P | 0 | * |
RRCA | – | – | 0 | – | 0 | * |
RRD | * | * | 0 | P | 0 | – |
SBC A,s | * | * | * | V | 1 | * |
SBC HL,ss | * | * | ? | V | 1 | * |
SCF | – | – | 0 | – | 0 | 1 |
SLA m | * | * | 0 | P | 0 | * |
SRA m | * | * | 0 | P | 0 | * |
SRL m | * | * | 0 | P | 0 | * |
SUB s | * | * | * | V | 1 | * |
XOR s | * | * | * | P | 0 | 0 |
10. Zobrazení obsahu příznakového registru F po provedení vybrané operace
V dalších kapitolách si na několika příkladech ukážeme, jakým způsobem jsou jednotlivé příznaky ovlivněny aritmetickými a jinými operacemi. Musíme být tedy schopni nějakým způsobem vytisknout hodnoty příznaků. Pro jednoduchost – protože pro vytištění příznaků sofistikovanějším způsobem je nutné vědět, jak příznaky používat :-) – se spokojíme s tím, že vytiskneme obsah celého osmibitového registru F. Jak to však můžeme provést? Prozatím umíme vytisknout numerickou hodnotu uloženou v registrovém páru BC, takže pouze musíme vynulovat obsah B a naopak přenést obsah registru F do registru C.
To ovšem nelze provést přímo instrukcí ld C, B, takže si musíme pomoci trikem – přesunem hodnot přes zásobník:
push AF ; uložíme pár AF na zásobník pop BC ; obnovíme původní obsah AF ze zásobníku, ovšem nyní do BC ld B, 0 ; vymažeme B (což byl obsah A), ponecháme jen C (což byl obsah F)
Nyní již registrový pár BC obsahuje původní hodnotu registru F v rozsahu 0 až 255, kterou lze snadno vytisknout na obrazovku:
call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla
Přesně tento postup použijeme v navazujících kapitolách.
11. Příznakové bity po provedení celočíselné operace 1+2
Nyní si vyzkoušejme, jaké příznakové bity budou nastaveny (či naopak nenastaveny) po provedení celočíselné operace 1+2 realizované instrukcí add, tedy konkrétně tímto způsobem:
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld A, 1 ; první sčítanec add A, 2 ; druhý sčítance + výsledek operace push AF ; uložíme pár AF na zásobník pop BC ; obnovíme původní obsah AF ze zásobníku, ovšem nyní do BC ld B, 0 ; vymažeme B (což byl obsah A), ponecháme jen C (což byl obsah F) call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu end ENTRY_POINT
Po překladu a spuštění tohoto příkladu zjistíme, že jsou všechny bity příznakového registru nulové:
Obrázek 11: Všechny bity příznakového registru F jsou nulové.
To konkrétně znamená následující:
Příznak | Význam | Hodnota | Vysvětlení |
---|---|---|---|
C | carry | 0 | bez přenosu do devátého bitu |
N | add/subtract | 0 | operace ADD |
V | overflow | 0 | bez přetečení do znaménkového bitu |
H | half carry | 0 | bez přenosu ze čtvrtého do pátého bitu |
Z | zero | 0 | výsledek je nenulový |
S | sign | 0 | výsledek je kladný |
Dnes již naposledy si ještě pro úplnost ukážeme, jak vypadá překlad do strojového kódu:
ENTRY_POINT EQU 8000 ROM_CLS EQU 0DAF OUT_NUM_1 EQU 1A1B ORG 8000 8000: label start 8000:CDAF0D CALL 0DAF 8003:3E01 LD A, 01 8005:C602 ADD A, 02 8007:F5 PUSH AF 8008:C1 POP BC 8009:0600 LD B, 00 800B:CD1B1A CALL 1A1B 800E:C9 RET 800F: END 8000 Emiting TAP basic loader Emiting TAP from 8000 to 800E
12. Příznakové bity po provedení celočíselné operace 0+0
Nyní předchozí demonstrační příklad nepatrně upravíme, a to takovým způsobem, že budeme provádět součet 0+0 (s nulovým výsledkem). Zdrojový kód příkladu se změní jen nepatrně – viz zvýrazněnou část kódu:
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld A, 0 ; první sčítanec add A, 0 ; druhý sčítance + výsledek operace push AF ; uložíme pár AF na zásobník pop BC ; obnovíme původní obsah AF ze zásobníku, ovšem nyní do BC ld B, 0 ; vymažeme B (což byl obsah A), ponecháme jen C (což byl obsah F) call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu end ENTRY_POINT
Výsledná hodnota uložená do příznakového bitu bude nyní odlišná:
Obrázek 12: Nastaven je pouze sedmý bit příznakového registru F.
Nastaven je tedy pouze příznak/bit zero znamenající nulový výsledek poslední aritmetické nebo logické operace. To konkrétně znamená následující:
Příznak | Význam | Hodnota | Vysvětlení |
---|---|---|---|
C | carry | 0 | bez přenosu do devátého bitu |
N | add/subtract | 0 | operace ADD |
V | overflow | 0 | bez přetečení do znaménkového bitu |
H | half carry | 0 | bez přenosu ze čtvrtého do pátého bitu |
Z | zero | 1 | výsledek je nulový |
S | sign | 0 | výsledek je kladný |
13. Příznakové bity po provedení operace 255+1
Nyní sečteme hodnoty 255+1. Výsledkem tedy bude nula (osmibitová hodnota přeteče přes 255), stejně jako tomu bylo v předchozím demonstračním příkladu. Ovšem budou stejně nastaveny i příznakové bity?
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld A, 255 ; první sčítanec add A, 1 ; druhý sčítance + výsledek operace push AF ; uložíme pár AF na zásobník pop BC ; obnovíme původní obsah AF ze zásobníku, ovšem nyní do BC ld B, 0 ; vymažeme B (což byl obsah A), ponecháme jen C (což byl obsah F) call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu end ENTRY_POINT
Výsledná dekadická hodnota 81 odpovídá binární hodnotě 01010001:
Obrázek 13: Příznakový registr obsahuje bity s hodnotami 01010001.
Výsledek součtu je tedy nulový, ovšem příznaky nám mohou napovědět, že se k výsledné nule došlo jiným způsobem:
Příznak | Význam | Hodnota | Vysvětlení |
---|---|---|---|
C | carry | 1 | s přenosem do devátého bitu (výsledek je větší než 255) |
N | add/subtract | 0 | operace ADD |
V | overflow | 0 | bez přetečení do znaménkového bitu |
H | half carry | 1 | s přenosem ze čtvrtého do pátého bitu |
Z | zero | 1 | výsledek je nulový |
S | sign | 0 | výsledek je kladný |
14. Příznakové bity po provedení operace 254+1
Zkusme nyní první sčítanec o jedničku snížit a provést aritmetickou operaci 254+1. Výsledkem bude 255, což je hodnota, která se vejde do osmibitového výsledného registru. Ovšem hodnoty příznaků budou opět odlišné:
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld A, 254 ; první sčítanec add A, 1 ; druhý sčítance + výsledek operace push AF ; uložíme pár AF na zásobník pop BC ; obnovíme původní obsah AF ze zásobníku, ovšem nyní do BC ld B, 0 ; vymažeme B (což byl obsah A), ponecháme jen C (což byl obsah F) call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu end ENTRY_POINT
Výsledná dekadická hodnota 168 odpovídá binární hodnotě 10101000:
Obrázek 14: Příznakový registr obsahuje bity s hodnotami 10101000.
Příznakové bity jsou opět prakticky zcela odlišné od předchozích výsledků:
Příznak | Význam | Hodnota | Vysvětlení |
---|---|---|---|
C | carry | 0 | bez přenosu do devátého bitu (výsledek je menší nebo roven 255) |
N | add/subtract | 0 | operace ADD |
V | overflow | 0 | bez přetečení do znaménkového bitu |
H | half carry | 0 | bez přenosu ze čtvrtého do pátého bitu |
Z | zero | 0 | výsledek je nenulový |
S | sign | 1 | výsledek je záporný |
15. Příznakové bity po provedení operace 255+255
Pokračujme dále. Zajímavé bude zjistit, jak se bude chovat operace 255+255. Na tuto operaci se můžeme dívat jako na součet dvou celých kladných čísel nebo naopak jako na součet dvou celých čísel záporných, protože hodnota 255 je binárně uložena jako 11111111, což ovšem je současně i hodnota –1 v případě, že budeme operace provádět ve dvojkovém doplňku (samotné operace budou stejné, pouze interpretace operandů a výsledku je jiná):
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld A, 255 ; první sčítanec add A, 255 ; druhý sčítance + výsledek operace push AF ; uložíme pár AF na zásobník pop BC ; obnovíme původní obsah AF ze zásobníku, ovšem nyní do BC ld B, 0 ; vymažeme B (což byl obsah A), ponecháme jen C (což byl obsah F) call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu end ENTRY_POINT
Příznakový registr bude obsahovat dekadickou hodnotu 185, což binárně odpovídá 10111001.
Obrázek 15: Příznakový registr obsahuje bity s hodnotami 10111001.
Příznakové bity jsou opět odlišné od předchozích výsledků:
Příznak | Význam | Hodnota | Vysvětlení |
---|---|---|---|
C | carry | 1 | s přenosem do devátého bitu (výsledek je větší než 255) |
N | add/subtract | 0 | operace ADD |
V | overflow | 0 | bez přetečení do znaménkového bitu |
H | half carry | 1 | s přenosem ze čtvrtého do pátého bitu |
Z | zero | 0 | výsledek je nenulový |
S | sign | 1 | výsledek je záporný |
16. Příznakové bity po provedení operace 100+100
V dnešním posledním demonstračním příkladu se pokusíme sečíst dvě hodnoty 100. Výsledkem je pochopitelně hodnota 200. Ovšem nyní dochází k zajímavé situaci, pokud budeme oba operandy i výsledek považovat za hodnoty se znaménkem reprezentované s dvojkovým doplňkem. Oba sčítance jsou stále kladnými hodnotami, ovšem 200 je bitově 11001000, což ve dvojkovém doplňku znamená –56 (a to ani nedošlo k přenosu!):
ENTRY_POINT equ $8000 ROM_CLS equ $0DAF OUT_NUM_1 equ $1A1B org ENTRY_POINT start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld A, 100 ; první sčítanec add A, 100 ; druhý sčítance + výsledek operace push AF ; uložíme pár AF na zásobník pop BC ; obnovíme původní obsah AF ze zásobníku, ovšem nyní do BC ld B, 0 ; vymažeme B (což byl obsah A), ponecháme jen C (což byl obsah F) call OUT_NUM_1 ; zavolání rutiny pro výpis celého čísla ret ; návrat z programu do BASICu end ENTRY_POINT
Na obrazovce ZX Spectra se zobrazí hodnota 140:
Obrázek 16: Příznakový registr obsahuje bity s hodnotami 10001100.
Příznakové bity jsou opět odlišné od předchozích výsledků:
Příznak | Význam | Hodnota | Vysvětlení |
---|---|---|---|
C | carry | 0 | bez přenosu do devátého bitu (výsledek je menší nebo roven 255) |
N | add/subtract | 0 | operace ADD |
V | overflow | 1 | s přetečením do znaménkového bitu |
H | half carry | 0 | bez přenosu ze čtvrtého do pátého bitu |
Z | zero | 0 | výsledek je nenulový |
S | sign | 1 | výsledek je záporný |
17. První shrnutí: význam příznaků C, V, S a Z
Nyní si již můžeme shrnout význam čtyř příznakových bitů při provádění aritmetických operací:
Příznak | S | Z | V | C | Poznámka |
---|---|---|---|---|---|
1+2 | 0 | 0 | 0 | 0 | kladný výsledek |
0+0 | 0 | 1 | 0 | 0 | nulový výsledek |
255+1 | 0 | 1 | 0 | 1 | nulový výsledek, ovšem vzniklý přenosem (0=256) |
254+1 | 1 | 0 | 0 | 0 | nenulový výsledek větší než 127 (a tedy záporný ve dvojkovém doplňku) |
255+255 | 1 | 0 | 0 | 1 | nenulový výsledek větší než 127, který ovšem vznikl přenosem |
100+100 | 1 | 0 | 1 | 0 | záporný výsledek vzniklý součtem dvou kladných čísel |
128+128 | 0 | 1 | 1 | 1 | nulový nezáporný výsledek, došlo ovšem jak k přetečení, tak i přenosu (toto je specifický případ) |
Zbývá nám popis dvou dalších příznaků N a především příznaku H. Tyto příznaky jsou použity například v instrukci DAA, což je pravděpodobně nejkomplikovanější a nejhůře (oficiálně) popsaná instrukce Z80 vůbec.
Obrázek 17: Příznakový registr po provedení operace 128+128.
18. Příloha: upravený soubor Makefile pro překlad demonstračních příkladů
Výše uvedené demonstrační příklady i příklady, které již byly popsány v předchozích sedmi článcích [1] [2], [3], [4], [5], [6], [7], je možné přeložit s využitím souboru Makefile, jehož aktuální verze vypadá následovně (pro překlad a slinkování je použit assembler Pasmo):
ASSEMBLER := pasmo all: 01.tap 02.tap 03.tap 04.tap 05.tap 06.tap 07.tap 08.tap 09.tap 10.tap \ 11.tap 12.tap 13.tap 14.tap 15.tap 16.tap 17.tap 18.tap 19.tap 20.tap \ 21.tap 22.tap 23.tap 24.tap 25.tap 26.tap 27.tap 28.tap 29.tap 30.tap \ 31.tap 32.tap 33.tap 34.tap 35.tap 36.tap 37.tap 38.tap 39.tap 40.tap \ 41.tap 42.tap 43.tap 44.tap 45.tap 46.tap 47.tap 48.tap 49.tap 50.tap \ 51.tap 52.tap 53.tap 54.tap 55.tap 56.tap 57.tap 58.tap 59.tap 60.tap \ 61.tap 62.tap 63.tap 64.tap 65.tap 66.tap 67.tap 68.tap 69.tap 70.tap \ 71.tap 72.tap clean: rm -f *.tap .PHONY: all clean 01.tap: 01-color-attribute.asm $(ASSEMBLER) -v -d --tap $< $@ > 01-color-attribute.lst 02.tap: 02-blinking-attribute.asm $(ASSEMBLER) -v -d --tap $< $@ > 02-blinking-attribute.lst 03.tap: 03-symbolic-names.asm $(ASSEMBLER) -v -d --tap $< $@ > 03-symbolic-names.lst 04.tap: 04-operators.asm $(ASSEMBLER) -v -d --tap $< $@ > 04-operators.lst 05.tap: 05-better-symbols.asm $(ASSEMBLER) -v -d --tap $< $@ > 05-better-symbols.lst 06.tap: 06-tapbas-v1.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 06-tapbas-v1.lst 07.tap: 07-tapbas-v2.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 07-tapbas-v2.lst 08.tap: 08-loop.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 08-loop.lst 09.tap: 09-loop.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 09-loop.lst 10.tap: 10-loop.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 10-loop.lst 11.tap: 11-loop.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 11-loop.lst 12.tap: 12-loop.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 12-loop.lst 13.tap: 13-loop.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 13-loop.lst 14.tap: 14-loop.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 14-loop.lst 15.tap: 15-loop.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 15-loop.lst 16.tap: 16-loop.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 16-loop.lst 17.tap: 17-loop.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 17-loop.lst 18.tap: 18-cls.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 18-cls.lst 19.tap: 19-print-char-call.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 19-print-char-call.lst 20.tap: 20-print-char-rst.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 20-print-char-rst.lst 21.tap: 21-print-char.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 21-print-char.lst 22.tap: 22-print-all-chars.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 22-print-all-chars.lst 23.tap: 23-print-all-chars.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 23-print-all-chars.lst 24.tap: 24-change-color.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 24-change-color.lst 25.tap: 25-change-flash.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 25-change-flash.lst 26.tap: 26-print-at.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 26-print-at.lst 27.tap: 27-print-string.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 27-print-string.lst 28.tap: 28-print-string.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 28-print-string.lst 29.tap: 29-print-colorized-string.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 29-print-colorized-string.lst 30.tap: 30-print-string-ROM.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 30-print-string-ROM.lst 31.tap: 31-attributes.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 31-attributes.lst 32.tap: 32-fill-in-vram.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 32-fill-in-vram.lst 33.tap: 33-fill-in-vram-no-ret.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 33-fill-in-vram-no-ret.lst 34.tap: 34-fill-in-vram-pattern.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 34-fill-in-vram-pattern.lst 35.tap: 35-slow-fill-in-vram.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 35-slow-fill-in-vram.lst 36.tap: 36-slow-fill-in-vram-no-ret.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 36-slow-fill-in-vram-no-ret.lst 37.tap: 37-fill-block.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 37-fill-block.lst 38.tap: 38-fill-block-with-pattern.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 38-fill-block-with-pattern.lst 39.tap: 39-fill-block-optimized.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 39-fill-block-optimized.lst 40.tap: 40-draw-char.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 40-draw-char.lst 41.tap: 41-draw-any-char.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 41-draw-any-char.lst 42.tap: 42-block-anywhere.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 42-block-anywhere.lst 43.tap: 43-block-anywhere-rrca.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 43-block-anywhere-rrca.lst 44.tap: 44-better-draw-char.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 44-better-draw-char.lst 45.tap: 45-even-better-draw-char.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 45-even-better-draw-char.lst 46.tap: 46-draw-char-at.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 46-draw-char-at.lst 47.tap: 47-draw-char-at-unrolled.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 47-draw-char-at-unrolled.lst 48.tap: 48-incorrect-print-string.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 48-incorrect-print-string.lst 49.tap: 49-correct-print-string.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 49-correct-print-string.lst 50.tap: 50-ascii-table.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 50-ascii-table.lst 51.tap: 51-plot-block.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 51-plot-block.lst 52.tap: 52-plot-pixel.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 52-plot-pixel.lst 53.tap: 53-plot-pixel.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 53-plot-pixel.lst 54.tap: 54-plot-pixel-on-background.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 54-plot-pixel-on-background.lst 55.tap: 55-plot-pixel-on-background.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 55-plot-pixel-on-background.lst 56.tap: 56-inverse-ascii-table.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 56-inverse-ascii-table.lst 57.tap: 57-plot-pixel-on-inverse-background.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 57-plot-pixel-on-inverse-background.lst 58.tap: 58-plot-inverse-pixel-on-inverse-background.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 58-plot-inverse-pixel-on-inverse-background.lst 59.tap: 59-configurable-ascii-table.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 59-configurable-ascii-table.lst 60.tap: 60-plot-over.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 60-plot-over.lst 61.tap: 61-print-number-A.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 61-print-number-A.lst 62.tap: 62-print-number-B.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 62-print-number-B.lst 63.tap: 63-print-number-C.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 63-print-number-C.lst 64.tap: 64-print-number-D.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 64-print-number-D.lst 65.tap: 65-more-numbers-A.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 65-more-numbers-A.lst 66.tap: 66-more-numbers-B.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 66-more-numbers-B.lst 67.tap: 67-print-flags-1.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 67-print-flags-1.lst 68.tap: 68-print-flags-2.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 68-print-flags-2.lst 69.tap: 69-print-flags-3.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 69-print-flags-3.lst 70.tap: 70-print-flags-4.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 70-print-flags-4.lst 71.tap: 71-print-flags-5.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 71-print-flags-5.lst 72.tap: 72-print-flags-6.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 72-print-flags-6.lst
19. Repositář s demonstračními příklady
V tabulce zobrazené pod tímto odstavcem jsou uvedeny odkazy na všechny prozatím popsané demonstrační příklady určené pro překlad a spuštění na osmibitovém domácím mikropočítači ZX Spectrum (libovolný model či jeho klon), které jsou psány v assembleru mikroprocesoru Zilog Z80. Pro překlad těchto demonstračních příkladů je možné použít například assembler Pasmo (viz též úvodní článek):
# | Soubor | Stručný popis | Adresa |
---|---|---|---|
1 | 01-color-attribute.asm | modifikace jednoho barvového atributu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/01-color-attribute.asm |
2 | 02-blinking-attribute.asm | barvový atribut s nastavením bitů pro blikání a vyšší intenzitu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/02-blinking-attribute.asm |
3 | 03-symbolic-names.asm | symbolická jména v assembleru | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/03-symbolic-names.asm |
4 | 04-operators.asm | operátory a operace se symbolickými hodnotami | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/04-operators.asm |
5 | 05-better-symbols.asm | tradičnější symbolická jména | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/05-better-symbols.asm |
6 | 06-tapbas-v1.asm | vygenerování BASICovského loaderu (neúplný příklad) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/06-tapbas-v1.asm |
7 | 07-tapbas-v2.asm | vygenerování BASICovského loaderu (úplný příklad) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/07-tapbas-v2.asm |
8 | 08-loop.asm | jednoduchá počítaná programová smyčka: naivní varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/08-loop.asm |
9 | 09-loop.asm | programová smyčka: zkrácení kódu pro vynulování použitých pracovních registrů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/09-loop.asm |
10 | 10-loop.asm | programová smyčka: optimalizace skoku na konci smyčky (instrukce DJNZ) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/10-loop.asm |
11 | 11-loop.asm | programová smyčka: optimalizace využití pracovních registrů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/11-loop.asm |
12 | 12-loop.asm | programová smyčka: použití pracovního registru IX | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/12-loop.asm |
13 | 13-loop.asm | programová smyčka: použití pracovního registru IY | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/13-loop.asm |
14 | 14-loop.asm | programová smyčka se šestnáctibitovým počitadlem, základní varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/14-loop.asm |
15 | 15-loop.asm | programová smyčka se šestnáctibitovým počitadlem, vylepšená varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/15-loop.asm |
16 | 16-loop.asm | použití relativního skoku a nikoli skoku absolutního | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/16-loop.asm |
17 | 17-loop.asm | programová smyčka: inc l namísto inc hl | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/17-loop.asm |
18 | 18-cls.asm | smazání obrazovky a otevření kanálu číslo 2 (screen) přes funkci v ROM | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/18-cls.asm |
19 | 19-print-char-call.asm | smazání obrazovky a výpis jednoho znaku na obrazovku přes funkci v ROM (použití instrukce CALL) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/19-print-char-call.asm |
20 | 20-print-char-rst.asm | smazání obrazovky a výpis jednoho znaku na obrazovku přes funkci v ROM (použití instrukce RST) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/20-print-char-rst.asm |
21 | 21-print-char.asm | pouze výpis jednoho znaku na obrazovku bez jejího smazání | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/21-print-char.asm |
22 | 22-print-all-chars.asm | výpis znakové sady znak po znaku (nekorektní verze příkladu) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/22-print-all-chars.asm |
23 | 23-print-all-chars.asm | výpis znakové sady znak po znaku (korektní verze příkladu) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/23-print-all-chars.asm |
24 | 24-change-color.asm | změna barvových atributů (popředí a pozadí) vypisovaných znaků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/24-change-color.asm |
25 | 25-change-flash.asm | povolení či zákaz blikání vypisovaných znaků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/25-change-flash.asm |
26 | 26-print-at.asm | výpis znaku či znaků na určené místo na obrazovce | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/26-print-at.asm |
27 | 27-print-string.asm | výpis celého řetězce explicitně zapsanou programovou smyčkou (základní varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/27-print-string.asm |
28 | 28-print-string.asm | výpis celého řetězce explicitně zapsanou programovou smyčkou (vylepšená varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/28-print-string.asm |
29 | 29-print-colorized-string.asm | výpis řetězce, který obsahuje i řídicí znaky pro změnu barvy atd. | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/29-print-colorized-string.asm |
30 | 30-print-string-ROM.asm | výpis řetězce s využitím služby/subrutiny uložené v ROM ZX Spectra | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/30-print-string-ROM.asm |
31 | 31-attributes.asm | modifikace atributů pro tisk řetězce subrutinou uloženou v ROM | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/31-attributes.asm |
32 | 32-fill-in-vram.asm | vyplnění celé bitmapy barvou popředí, návrat do systému | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/32-fill-in-vram.asm |
33 | 33-fill-in-vram-no-ret.asm | vyplnění celé bitmapy barvou popředí, bez návratu do systému | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/33-fill-in-vram-no-ret.asm |
34 | 34-fill-in-vram-pattern.asm | vyplnění celé bitmapy zvoleným vzorkem | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/34-fill-in-vram-pattern.asm |
35 | 35-slow-fill-in-vram.asm | pomalé vyplnění celé bitmapy, vizualizace struktury bitmapy | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/35-slow-fill-in-vram.asm |
36 | 36-slow-fill-in-vram-no-ret.asm | pomalé vyplnění celé bitmapy, vizualizace struktury bitmapy, bez návratu do systému | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/36-slow-fill-in-vram-no-ret.asm |
37 | 37-fill-block.asm | vykreslení bloku 8×8 pixelů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/37-fill-block.asm |
38 | 38-fill-block-with-pattern.asm | vykreslení bloku 8×8 pixelů zvoleným vzorkem | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/38-fill-block-with-pattern.asm |
39 | 39-fill-block-optimized.asm | optimalizace předchozího příkladu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/39-fill-block-optimized.asm |
40 | 40-draw-char.asm | vykreslení znaku do levého horního rohu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/40-draw-char.asm |
41 | 41-draw-any-char.asm | podprogram pro vykreslení libovolně zvoleného znaku do levého horního rohu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/41-draw-any-char.asm |
42 | 42-block-anywhere.asm | podprogramy pro vykreslení bloku 8×8 pixelů kamkoli na obrazovku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/42-block-anywhere.asm |
43 | 43-block-anywhere-rrca.asm | podprogramy pro vykreslení bloku 8×8 pixelů kamkoli na obrazovku, vylepšená varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/43-block-anywhere-rrca.asm |
44 | 44-better-draw-char.asm | vykreslení znaku v masce 8×8 pixelů, vylepšená varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/44-better-draw-char.asm |
45 | 45-even-better-draw-char.asm | posun offsetu pro vykreslení dalšího znaku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/45-even-better-draw-char.asm |
46 | 46-draw-char-at.asm | vykreslení znaku v masce 8×8 pixelů kamkoli na obrazovku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/46-draw-char-at.asm |
47 | 47-draw-char-at-unrolled.asm | vykreslení znaku v masce 8×8 pixelů kamkoli na obrazovku | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/47-draw-char-at-unrolled.asm |
48 | 48-incorrect-print-string.asm | tisk řetězce, nekorektní varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/48-incorrect-print-string.asm |
49 | 49-correct-print-string.asm | tisk řetězce, korektní varianta | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/49-correct-print-string.asm |
50 | 50-ascii-table.asm | tisk několika bloků ASCII tabulky | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/50-ascii-table.asm |
51 | 51-plot-block.asm | vykreslení pixelu verze 1: zápis celého bajtu na pozici pixelu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/51-plot-block.asm |
52 | 52-plot-pixel.asm | vykreslení pixelu verze 2: korektní vykreslení jednoho pixelu, ovšem překreslení celého bajtu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/52-plot-pixel.asm |
53 | 53-plot-pixel.asm | vykreslení pixelu verze 3: vylepšená verze předchozího demonstračního příkladu | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/53-plot-pixel.asm |
54 | 54-plot-pixel-on-background.asm | vykreslení pixelu vůči pozadí (nekorektní varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/54-plot-pixel-on-background.asm |
55 | 55-plot-pixel-on-background.asm | vykreslení pixelu vůči pozadí (korektní varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/55-plot-pixel-on-background.asm |
56 | 56-inverse-ascii-table.asm | vykreslení ASCII tabulky inverzní barvou (inkoust vs. papír) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/56-inverse-ascii-table.asm |
57 | 57-plot-pixel-on-inverse-background.asm | vykreslení pixelů barvou papíru proti inverzní ASCII tabulce | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/57-plot-pixel-on-inverse-background.asm |
58 | 58-plot-inverse-pixel-on-inverse-background.asm | vykreslení pixelů inverzní barvou proti inverzní ASCII tabulce | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm58-plot-inverse-pixel-on-inverse-background.asm/ |
59 | 59-configurable-ascii-table.asm | vykreslení ASCII tabulky buď přímo inkoustem nebo inverzně | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/59-configurable-ascii-table.asm |
60 | 60-plot-over.asm | přibližná implementace příkazu PLOT OVER | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/60-plot-over.asm |
61 | 61-print-number-A.asm | ukázka použití podprogramu pro tisk celého čísla | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/61-print-number-A.asm |
62 | 62-print-number-B.asm | pokus o vytištění záporných čísel | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/62-print-number-B.asm |
63 | 63-print-number-C.asm | tisk maximální podporované hodnoty 9999 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/63-print-number-C.asm |
64 | 64-print-number-D.asm | tisk vyšší než podporované hodnoty 10000 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/64-print-number-D.asm |
65 | 65-more-numbers-A.asm | vytištění číselné řady | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/65-more-numbers-A.asm |
66 | 66-more-numbers-B.asm | kombinace tisku celočíselných hodnot s dalšími subrutinami | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/66-more-numbers-B.asm |
67 | 67-print-flags-1.asm | příznakové bity po provedení celočíselné operace 1+2 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/67-print-flags-1.asm |
68 | 68-print-flags-2.asm | příznakové bity po provedení celočíselné operace 0+0 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/68-print-flags-2.asm |
69 | 69-print-flags-3.asm | příznakové bity po provedení operace 255+1 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/69-print-flags-3.asm |
70 | 70-print-flags-4.asm | příznakové bity po provedení operace 254+1 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/70-print-flags-4.asm |
71 | 71-print-flags-5.asm | příznakové bity po provedení operace 255+255 | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/71-print-flags-5.asm |
72 | 72-print-flags-6.asm | výsledek operace 100+100, nastavení příznakových bitů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/72-print-flags-6.asm |
73 | 73-print-flags-7.asm | výsledek operace 128+128, nastavení příznakových bitů | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/73-print-flags-7.asm |
7× | Makefile | Makefile pro překlad a slinkování všech demonstračních příkladů do podoby obrazu magnetické pásky | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/Makefile |
20. Odkazy na Internetu
- z80 standalone assembler
https://www.asm80.com/onepage/asmz80.html - The ZX BASIC Compiler
https://www.boriel.com/pages/the-zx-basic-compiler.html - Z80 Assembly programming for the ZX Spectrum
https://www.chibiakumas.com/z80/ZXSpectrum.php - 8-BIT SMACKDOWN! 65C02 vs. Z80: slithy VLOGS #6
https://www.youtube.com/watch?v=P1paVoFEvyc - Instrukce mikroprocesoru Z80
https://clrhome.org/table/ - Z80 instructions: adresní režimy atd.
https://jnz.dk/z80/instructions.html - Z80 Instruction Groups
https://jnz.dk/z80/instgroups.html - Elena, New programming language for the ZX Spectrum Next
https://vintageisthenewold.com/elena-new-programming-language-for-the-zx-spectrum-next/ - Sinclair BASIC
https://worldofspectrum.net/legacy-info/sinclair-basic/ - Grafika na osmibitových počítačích firmy Sinclair
https://www.root.cz/clanky/grafika-na-osmibitovych-pocitacich-firmy-sinclair/ - Grafika na osmibitových počítačích firmy Sinclair II
https://www.root.cz/clanky/grafika-na-osmibitovych-pocitacich-firmy-sinclair-ii/ - HiSoft BASIC
https://worldofspectrum.net/infoseekid.cgi?id=0008249 - YS MegaBasic
https://worldofspectrum.net/infoseekid.cgi?id=0008997 - Beta Basic
https://worldofspectrum.net/infoseekid.cgi?id=0007956 - BASIC+
https://worldofspectrum.net/infoseekid.php?id=0014277 - Spectrum ROM Memory Map
https://skoolkit.ca/disassemblies/rom/maps/all.html - Goto subroutine
https://skoolkit.ca/disassemblies/rom/asm/7783.html - Spectrum Next: The Evolution of the Speccy
https://www.specnext.com/about/ - Sedmdesátiny assemblerů: lidsky čitelný strojový kód
https://www.root.cz/clanky/sedmdesatiny-assembleru-lidsky-citelny-strojovy-kod/ - Programovací jazyk BASIC na osmibitových mikropočítačích
https://www.root.cz/clanky/programovaci-jazyk-basic-na-osmibitovych-mikropocitacich/ - Programovací jazyk BASIC na osmibitových mikropočítačích (2)
https://www.root.cz/clanky/programovaci-jazyk-basic-na-osmibitovych-mikropocitacich-2/#k06 - Programovací jazyk BASIC na osmibitových mikropočítačích (3)
https://www.root.cz/clanky/programovaci-jazyk-basic-na-osmibitovych-mikropocitacich-3/ - Sinclair BASIC (Wikipedia CZ)
http://cs.wikipedia.org/wiki/Sinclair_BASIC - Assembly Language: Still Relevant Today
http://wilsonminesco.com/AssyDefense/ - Programovani v assembleru na OS Linux
http://www.cs.vsb.cz/grygarek/asm/asmlinux.html - Why Assembly Language Programming? (Why Learning Assembly Language Is Still a Good Idea)
https://wdc65×x.com/markets/education/why-assembly-language-programming/ - Low Fat Computing
http://www.ultratechnology.com/lowfat.htm - Assembly Language
https://www.cleverism.com/skills-and-tools/assembly-language/ - Why do we need assembly language?
https://cs.stackexchange.com/questions/13287/why-do-we-need-assembly-language - Assembly language (Wikipedia)
https://en.wikipedia.org/wiki/Assembly_language#Historical_perspective - Assembly languages
https://curlie.org/Computers/Programming/Languages/Assembly/ - vasm
http://sun.hasenbraten.de/vasm/ - B-ELITE
https://jsj.itch.io/b-elite - ZX-Spectrum Child
http://www.dotkam.com/2008/11/19/zx-spectrum-child/ - Speccy.cz
http://www.speccy.cz/ - Planet Sinclair
http://www.nvg.ntnu.no/sinclair/ - World of Spectrum
http://www.worldofspectrum.org/ - The system variables
https://worldofspectrum.org/ZXBasicManual/zxmanchap25.html - ZX Spectrum manual: chapter #17 Graphics
https://worldofspectrum.org/ZXBasicManual/zxmanchap17.html - Why does Sinclair BASIC have two formats for storing numbers in the same structure?
https://retrocomputing.stackexchange.com/questions/8834/why-does-sinclair-basic-have-two-formats-for-storing-numbers-in-the-same-structu - Plovoucí řádová čárka na ZX Spectru
https://www.root.cz/clanky/norma-ieee-754-a-pribuzni-formaty-plovouci-radove-tecky/#k05 - Norma IEEE 754 a příbuzní: formáty plovoucí řádové tečky
https://www.root.cz/clanky/norma-ieee-754-a-pribuzni-formaty-plovouci-radove-tecky/#k05 - 1A1B: THE ‚REPORT AND LINE NUMBER PRINTING‘ SUBROUTINE
https://skoolkid.github.io/rom/asm/1A1B.html - 2DE3: THE ‚PRINT A FLOATING-POINT NUMBER‘ SUBROUTINE
https://skoolkid.github.io/rom/asm/2DE3.html - 5C63: STKBOT – Address of bottom of calculator stack
https://skoolkid.github.io/rom/asm/5C63.html - 5C65: STKEND – Address of start of spare space
https://skoolkid.github.io/rom/asm/5C65.html - Why does Sinclair BASIC have two formats for storing numbers in the same structure?
https://retrocomputing.stackexchange.com/questions/8834/why-does-sinclair-basic-have-two-formats-for-storing-numbers-in-the-same-structu - Chapter 24: The memory
https://worldofspectrum.org/ZXBasicManual/zxmanchap24.html - Survey of Floating-Point Formats
https://mrob.com/pub/math/floatformats.html - Convert an 8bit number to hex in z80 assembler
https://stackoverflow.com/questions/22838444/convert-an-8bit-number-to-hex-in-z80-assembler - 80 MICROPROCESSOR Instruction Set Summary
http://www.textfiles.com/programming/CARDS/z80