Obsah
1. Aritmetické operace s hodnotami uloženými binárně i v BCD
2. Podprogram pro tisk hexadecimální cifry i osmibitové hexadecimální hodnoty
3. Demonstrační příklad, který vytiskne několik specifických hexadecimálních hodnot na obrazovku
4. Optimalizace předchozího demonstračního příkladu
5. Rutina pro tisk tabulky s větším množstvím hexadecimálních hodnot
6. Úplný zdrojový kód dnešního třetího demonstračního příkladu
7. Součet osmibitových hodnot uložených ve standardním binárním kódu
8. Tisk tabulky se sčítanci i součty
9. Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu
10. Uložení numerických hodnot ve formátu BCD a Packed BCD
11. Podpora pro výpočty v BCD v instrukčních sadách mikroprocesorů
12. Příznak half carry a instrukce DAA
13. Vliv příznaků a hodnoty v akumulátoru na operaci DAA
14. Realizace součtu dvou numerických hodnot uložených ve formátu Packed BCD
15. Tisk tabulky se sčítanci i součty
16. Úplný zdrojový kód dnešního pátého demonstračního příkladu
17. Obsah následujícího článku
18. Příloha: upravený soubor Makefile pro překlad demonstračních příkladů
19. Repositář s demonstračními příklady
1. Aritmetické operace s hodnotami uloženými binárně i v BCD
Na předchozí článek o tvorbě aplikací pro slavný osmibitový mikropočítač ZX Spectrum v assembleru dnes navážeme. Připomeňme si, že minule jsme si nejprve ukázali, jakým způsobem lze využít rutinu pojmenovanou OUT_NUM1 a uloženou v paměti ROM pro tisk dekadických hodnot v rozsahu od 0 do 9999. Dále jsme si popsali funkce a vlastnosti pěti základních příznaků (flags) mikroprocesoru Zilog Z80 – carry, zero, add/subtract, overflow a sign.
Obrázek 1: Výpis numerických hodnot na obrazovku podprogramem uloženým v ROM. Konkrétně se jedná o minule popsanou subrutinu nazvanou OUT_NUM1.
Dnes si nejprve ukážeme, jak by mohla vypadat poměrně přímočaře naprogramovaná subrutina určená pro tisk osmibitové hexadecimální hodnoty v rozsahu od 0×00 do 0×ff. Uvidíme, že se v této subrutině použije podmíněný skok. Ovšem ve skutečnosti je možné využít určité triky a napsat tuto subrutinu i bez skoku, a to konkrétně tak, že se využije doposud nepopsaný příznak half carry a s ním související instrukce DAA. Proto si nejprve ukážeme, jak probíhá součet (nebo i rozdíl) hodnot uložených v binárním kódu i v kódu BCD (Binary-coded decimal), protože jak příznak half carry, tak i instrukce DAA původně s BCD velmi úzce souvisí (resp. přesněji řečeno souvisí s variantou, která se nazývá packed BCD).
Obrázek 2: Výsledek pokusu o vytištění záporného čísla standardní subrutinou OUT_NUM1.
2. Podprogram pro tisk hexadecimální cifry i osmibitové hexadecimální hodnoty
Ukažme si nejprve, jak by mohla vypadat prozatím dosti primitivně naprogramovaná subrutina určená pro tisk jedné šestnáctkové (hexadecimální) cifry. Tato subrutina předpokládá, že v pracovním registru A (akumulátoru) bude uložena hodnota 0×00 až 0×0f, přičemž spodní cifra 0×0 až 0×f se vytiskne k tomu určeným standardním podprogramem z ROM. V podstatě nám pouze postačuje určit, zda se má tisknout ASCII hodnota „0“ až „9“ či „A“ až „F“. Tyto hodnoty netvoří ucelenou řadu, takže musíme provést podmíněný skok:
print_hex_digit: cp 0x0a ; test, jestli je číslice menší než 10 jr c, print_0_to_9 ; ok, hodnota je menší než 10, budeme tedy tisknout desítkovou číslici add A, 65-10 ; ASCII kód znaku 'A', ovšem začínáme od desítky, ne od nuly rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku ret ; návrat ze subrutiny print_0_to_9: add A, 48 ; ASCII kód znaku '0' rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku ret ; návrat ze subrutiny
Aby se vytiskla celá osmibitová hodnota 0×00 až 0×FF, je nutné provést tisk vyšší cifry a poté cifry nižší. To lze realizovat velmi snadno s využitím bitových posunů spojených s maskováním:
print_hex_number: push AF ; uschovat A pro pozdější využití rrca ; rotace o čtyři bity doprava rrca rrca rrca and $0f ; zamaskovat horní čtyři bity call print_hex_digit; vytisknout hexa číslici pop AF ; obnovit A and $0f ; zamaskovat horní čtyři bity call print_hex_digit; vytisknout hexa číslici ret ; a návrat z podprogramu
Jak je to obvyklé prakticky ve všech instrukčních sadách, je možné dvojici instrukcí CALL+RET nahradit za jedinou instrukci přímého skoku. Podprogram pro tisk hexadecimální hodnoty tedy pozměníme takto:
print_hex_number: push AF ; uschovat A pro pozdější využití rrca ; rotace o čtyři bity doprava rrca rrca rrca and $0f ; zamaskovat horní čtyři bity call print_hex_digit; vytisknout hexa číslici pop AF ; obnovit A and $0f ; zamaskovat horní čtyři bity jp print_hex_digit; vytisknout hexa číslici ; a návrat z podprogramu
3. Demonstrační příklad, který vytiskne několik specifických hexadecimálních hodnot na obrazovku
Výše uvedenou rutinu několikrát zavoláme a získáme na tak obrazovce několik hexadecimálních hodnot:
Obrázek 3: Několik hexadecimálních hodnot vytištěných na obrazovku ZX Spectra.
Úplný zdrojový kód dnešního prvního demonstračního příkladu vypadá následovně:
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, 0x00 ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0x01 ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0x09 ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0x99 ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0x0a ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0xa0 ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0xba ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0xff ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ret ; návrat z programu do BASICu print_hex_number: push AF ; uschovat A pro pozdější využití rrca ; rotace o čtyři bity doprava rrca rrca rrca and $0f ; zamaskovat horní čtyři bity call print_hex_digit; vytisknout hexa číslici pop AF ; obnovit A and $0f ; zamaskovat horní čtyři bity call print_hex_digit; vytisknout hexa číslici ret ; a návrat z podprogramu print_hex_digit: cp 0x0a ; test, jestli je číslice menší než 10 jr c, print_0_to_9 ; ok, hodnota je menší než 10, budeme tedy tisknout desítkovou číslici add A, 65-10 ; ASCII kód znaku 'A', ovšem začínáme od desítky, ne od nuly rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku ret ; návrat ze subrutiny print_0_to_9: add A, 48 ; ASCII kód znaku '0' rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku ret ; návrat ze subrutiny new_line: ld A, 0x0d ; kód znaku pro odřádkování rst 0x10 ; zavolání rutiny v ROM ret ; návrat ze subrutiny end ENTRY_POINT
A podívejme se ještě na způsob překladu tohoto zdrojového kódu z assembleru 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:3E00 LD A, 00 8005:CD4480 CALL 8044 8008:CD6180 CALL 8061 800B:3E01 LD A, 01 800D:CD4480 CALL 8044 8010:CD6180 CALL 8061 8013:3E09 LD A, 09 8015:CD4480 CALL 8044 8018:CD6180 CALL 8061 801B:3E99 LD A, 99 801D:CD4480 CALL 8044 8020:CD6180 CALL 8061 8023:3E0A LD A, 0A 8025:CD4480 CALL 8044 8028:CD6180 CALL 8061 802B:3EA0 LD A, A0 802D:CD4480 CALL 8044 8030:CD6180 CALL 8061 8033:3EBA LD A, BA 8035:CD4480 CALL 8044 8038:CD6180 CALL 8061 803B:3EFF LD A, FF 803D:CD4480 CALL 8044 8040:CD6180 CALL 8061 8043:C9 RET 8044: label print_hex_number 8044:F5 PUSH AF 8045:0F RRCA 8046:0F RRCA 8047:0F RRCA 8048:0F RRCA 8049:E60F AND 0F 804B:CD5580 CALL 8055 804E:F1 POP AF 804F:E60F AND 0F 8051:CD5580 CALL 8055 8054:C9 RET 8055: label print_hex_digit 8055:FE0A CP 0A 8057:3804 JR C, 805D 8059:C637 ADD A, 37 805B:D7 RST 10 805C:C9 RET 805D: label print_0_to_9 805D:C630 ADD A, 30 805F:D7 RST 10 8060:C9 RET 8061: label new_line 8061:3E0D LD A, 0D 8063:D7 RST 10 8064:C9 RET 8065: END 8000 Emiting TAP basic loader Emiting TAP from 8000 to 8064
4. Optimalizace předchozího demonstračního příkladu
Podprogram pro tisk jedné hexadecimální číslice lze dále zjednodušit tak, že pro hodnoty „A“ až „F“ nejprve provedeme mezivýpočet a poté se budeme tvářit, že se jedná o hodnotu „0“ až „9“:
print_hex_digit: cp 0x0a ; test, jestli je číslice menší než 10 jr c, print_0_to_9 ; ok, hodnota je menší než 10, budeme tedy tisknout desítkovou číslici add A, 65-10-48 ; ASCII kód znaku 'A', ovšem začínáme od desítky, ne od nuly (+ update pro další ADD) print_0_to_9: add A, 48 ; ASCII kód znaku '0' rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku ret ; návrat ze subrutiny
Výsledkem by měla být naprosto stejná obrazovka:
Obrázek 4: Několik hexadecimálních hodnot vytištěných na obrazovku ZX Spectra (totožné s předchozím screenshotem).
Již ve druhé kapitole jsme si řekli, že kód je možné velmi snadno (i když jen nepatrně) optimalizovat tak, že se dvojice za sebou jdoucích instrukcí CALL+RET nahradí za přímý skok. Výsledkem bude tento kód:
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, 0x00 ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0x01 ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0x09 ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0x99 ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0x0a ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0xa0 ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0xba ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ld A, 0xff ; vytisknout hexa hodnotu s přechodem na nový řádek call print_hex_number call new_line ret ; návrat z programu do BASICu print_hex_number: push AF ; uschovat A pro pozdější využití rrca ; rotace o čtyři bity doprava rrca rrca rrca and $0f ; zamaskovat horní čtyři bity call print_hex_digit; vytisknout hexa číslici pop AF ; obnovit A and $0f ; zamaskovat horní čtyři bity jp print_hex_digit ; vytisknout hexa číslici a návrat z podprogramu print_hex_digit: cp 0x0a ; test, jestli je číslice menší než 10 jr c, print_0_to_9 ; ok, hodnota je menší než 10, budeme tedy tisknout desítkovou číslici add A, 65-10-48 ; ASCII kód znaku 'A', ovšem začínáme od desítky, ne od nuly (+ update pro další ADD) print_0_to_9: add A, 48 ; ASCII kód znaku '0' rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku ret ; návrat ze subrutiny new_line: ld A, 0x0d ; kód znaku pro odřádkování rst 0x10 ; zavolání rutiny v ROM ret ; návrat ze subrutiny end ENTRY_POINT
Ještě si pro úplnost uveďme symbolicky popsanou podobu výsledného strojového kódu, který je o tři bajty kratší než kód originální:
ENTRY_POINT EQU 8000 ROM_CLS EQU 0DAF OUT_NUM_1 EQU 1A1B ORG 8000 8000: label start 8000:CDAF0D CALL 0DAF 8003:3E00 LD A, 00 8005:CD4480 CALL 8044 8008:CD5E80 CALL 805E 800B:3E01 LD A, 01 800D:CD4480 CALL 8044 8010:CD5E80 CALL 805E 8013:3E09 LD A, 09 8015:CD4480 CALL 8044 8018:CD5E80 CALL 805E 801B:3E99 LD A, 99 801D:CD4480 CALL 8044 8020:CD5E80 CALL 805E 8023:3E0A LD A, 0A 8025:CD4480 CALL 8044 8028:CD5E80 CALL 805E 802B:3EA0 LD A, A0 802D:CD4480 CALL 8044 8030:CD5E80 CALL 805E 8033:3EBA LD A, BA 8035:CD4480 CALL 8044 8038:CD5E80 CALL 805E 803B:3EFF LD A, FF 803D:CD4480 CALL 8044 8040:CD5E80 CALL 805E 8043:C9 RET 8044: label print_hex_number 8044:F5 PUSH AF 8045:0F RRCA 8046:0F RRCA 8047:0F RRCA 8048:0F RRCA 8049:E60F AND 0F 804B:CD5480 CALL 8054 804E:F1 POP AF 804F:E60F AND 0F 8051:C35480 JP 8054 8054: label print_hex_digit 8054:FE0A CP 0A 8056:3802 JR C, 805A 8058:C607 ADD A, 07 805A: label print_0_to_9 805A:C630 ADD A, 30 805C:D7 RST 10 805D:C9 RET 805E: label new_line 805E:3E0D LD A, 0D 8060:D7 RST 10 8061:C9 RET 8062: END 8000 Emiting TAP basic loader Emiting TAP from 8000 to 8061
5. Rutina pro tisk tabulky s větším množstvím hexadecimálních hodnot
Předchozí kód neustále opakoval stejnou sekvenci instrukcí:
- Načtení hodnoty, která se má vypsat
- Zavolání subrutiny pro tisk této hodnoty
- Zavolání subrutiny pro odřádkování
Ve chvíli, kdy se tiskne větší množství hodnot, může být výhodnější si nejprve připravit pole se všemi hodnotami. Pole je buď nutné ukončit nějakou předem známou hodnotou (v našem případě nulou), nebo si pamatovat délku pole popř. adresu posledního prvku. My použijeme první způsob, tedy vložení „zarážky“ na konec pole:
numbers: db 0x01, 0x09, 0x99, 0xa0, 0xa0, 0xba, 0xff, 0x00
Dále lze vytvořit programovou smyčku, která postupně načítá hodnoty z pole a tiskne je. Pokud se dojde na koncový prvek, je subrutina ukončena instrukcí RET (což je v našem případě podmíněná instrukce testující příznak zero):
ld HL, numbers ; statické pole s hodnotami, které se mají vytisknout + zarážkou loop: ld A, (HL) ; načíst další hodnotu ze statického pole or A ; test na nulu ret z ; návrat z programu do BASICU inc HL ; adresa dalšího prvku v poli call print_hex_number ; tisk hexadecimální hodnoty call new_line ; s přechodem na nový řádek jp loop ; zpracování další hodnoty
Obrázek 5: Opět si zobrazíme sloupeček s několika hexadecimálními hodnotami. Nyní nelze kvůli logice programové smyčky vytisknout nulovou hodnotu, ovšem úprava je jednoduchá a ponechám ji na váženém čtenáři.
6. Úplný zdrojový kód dnešního třetího demonstračního příkladu
Úplný zdrojový kód demonstračního příkladu popsaného v předchozí kapitole je dostupný na adrese https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/76-print-hex-numbers.asm:
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 HL, numbers ; statické pole s hodnotami, které se mají vytisknout + zarážkou loop: ld A, (HL) ; načíst další hodnotu ze statického pole or A ; test na nulu ret z ; návrat z programu do BASICU inc HL ; adresa dalšího prvku v poli call print_hex_number ; tisk hexadecimální hodnoty call new_line ; s přechodem na nový řádek jp loop ; zpracování další hodnoty numbers: db 0x01, 0x09, 0x99, 0xa0, 0xa0, 0xba, 0xff, 0x00 print_hex_number: push AF ; uschovat A pro pozdější využití rrca ; rotace o čtyři bity doprava rrca rrca rrca and $0f ; zamaskovat horní čtyři bity call print_hex_digit; vytisknout hexa číslici pop AF ; obnovit A and $0f ; zamaskovat horní čtyři bity jp print_hex_digit ; vytisknout hexa číslici a návrat z podprogramu print_hex_digit: cp 0x0a ; test, jestli je číslice menší než 10 jr c, print_0_to_9 ; ok, hodnota je menší než 10, budeme tedy tisknout desítkovou číslici add A, 65-10-48 ; ASCII kód znaku 'A', ovšem začínáme od desítky, ne od nuly (+ update pro další ADD) print_0_to_9: add A, 48 ; ASCII kód znaku '0' rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku ret ; návrat ze subrutiny new_line: ld A, 0x0d ; kód znaku pro odřádkování rst 0x10 ; zavolání rutiny v ROM ret ; návrat ze subrutiny end ENTRY_POINT
Samozřejmě si opět pro úplnost ukážeme, jak byl tento zdrojový text přeložen 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:211380 LD HL, 8013 8006: label loop 8006:7E LD A, (HL) 8007:B7 OR A 8008:C8 RET Z 8009:23 INC HL 800A:CD1B80 CALL 801B 800D:CD3580 CALL 8035 8010:C30680 JP 8006 8013: label numbers 8013:010999A0 DEFB of 8 bytes 8017:A0BAFF00 801B: label print_hex_number 801B:F5 PUSH AF 801C:0F RRCA 801D:0F RRCA 801E:0F RRCA 801F:0F RRCA 8020:E60F AND 0F 8022:CD2B80 CALL 802B 8025:F1 POP AF 8026:E60F AND 0F 8028:C32B80 JP 802B 802B: label print_hex_digit 802B:FE0A CP 0A 802D:3802 JR C, 8031 802F:C607 ADD A, 07 8031: label print_0_to_9 8031:C630 ADD A, 30 8033:D7 RST 10 8034:C9 RET 8035: label new_line 8035:3E0D LD A, 0D 8037:D7 RST 10 8038:C9 RET 8039: END 8000 Emiting TAP basic loader Emiting TAP from 8000 to 8038
7. Součet osmibitových hodnot uložených ve standardním binárním kódu
V dalším kroku vytvoříme program, který na obrazovku ZX Spectra vytiskne výsledky součtu vždy dvou osmibitových hodnot, které jsou uloženy ve standardním binárním formátu. Jedná se tedy o celočíselné hodnoty v rozsahu 0 až 255. Jak jednotlivé sčítance, tak i výsledek součtu jsou vypsány v hexadecimálním tvaru (proč tomu tak je, uvidíme v kapitole o BCD):
Obrázek 6: V každém sloupci jsou vždy nejprve uvedeny oba sčítance a pod nimi i výsledek součtu.
Na dalším obrázku je ukázáno, jak se mají číst zobrazené hodnoty. V červeném rámečku je vypsána operace 1+2=3 (stejné jak v decimálním tak i hexadecimálním tvaru). V modrém rámečku je vypsána operace 6+9=15, což v hexadecimálním tvaru odpovídá hodnotě 0×0f:
Obrázek 7: Základní aritmetika: 1+2=3 a 6+9=15 (0×0f).
8. Tisk tabulky se sčítanci i součty
Podívejme se nyní na způsob zobrazení „tabulek“ se součty. Nejdříve je nutné deklarovat dvojici polí. Pole array1 obsahuje první sčítance, pole array2 sčítance druhé:
array1: db 0x00, 0x01, 0x05, 0x09, 0x09, 0x09, 0x10, 0x10, 0xa0, 0xfe, 0xff array2: db 0x01, 0x02, 0x05, 0x01, 0x06, 0x07, 0x09, 0x10, 0x01, 0x01, 0x01
Dále si vytvoříme podprogram, který vytiskne celou řadu hodnot. Počet těchto hodnot je uložen v pracovním registru B a adresa pole s hodnotami v registrovém páru HL. Povšimněte si, že počet hodnot je zvolen takovým způsobem, aby se za poslední hodnotou již netiskla mezera: 11×3=33 (celkem je k dispozici 32 textových sloupců):
; podprogram pro tisk sekvence numerických hodnot v hexadecimálním formátu ; vstupy: ; HL - ukazatel na pole s hodnotami ; B - počet hodnot (délka pole) print_numbers: next_item: ld A, (HL) ; načíst hodnotu z pole inc HL ; přechod na další prvek pole call print_hex_number ; vytisknout hexa hodnotu ld A, B cp 1 ; za poslední hodnotou už nechceme tisknout mezeru jr Z, skip ; přeskočení tisku mezery u poslední hodnoty call space skip: djnz next_item ; zpracování dalšího prvku pole ret
A konečně poslední sekvence instrukcí vypočítá a následně vytiskne součet hodnot, a to bez nutnosti jejich uložení do třetího pole:
ld DE, array1 ; adresa pole s první řadou sčítanců ld HL, array2 ; adresa pole se druhou řadou sčítanců ld B, 11 next_add: ld A, (DE) ; načíst první sčítanec z pole add A, (HL) ; načíst druhý sčítanec z pole inc DE ; posun ukazatele na další sčítanec inc HL ; dtto call print_hex_number ; vytisknout hexa hodnotu výsledku call space djnz next_add ; kontrola počtu zobrazených výsledků ret
9. Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu
Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu popsaného v předchozích dvou kapitolách je dostupný na adrese https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/77-add-hex-numbers.asm:
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 HL, array1 ; vytištění 11 hodnot z pole array1 v hexadecimálním formátu ld B, 11 call print_numbers ld HL, array2 ; vytištění 11 hodnot z pole array2 v hexadecimálním formátu ld B, 11 call print_numbers call new_line ; odřádkování call new_line ; (chyba v ROM subrutině nebo užitečná vlastnost?) ld DE, array1 ; adresa pole s první řadou sčítanců ld HL, array2 ; adresa pole se druhou řadou sčítanců ld B, 11 next_add: ld A, (DE) ; načíst první sčítanec z pole add A, (HL) ; načíst druhý sčítanec z pole inc DE ; posun ukazatele na další sčítanec inc HL ; dtto call print_hex_number ; vytisknout hexa hodnotu výsledku call space djnz next_add ; kontrola počtu zobrazených výsledků ret ; podprogram pro tisk sekvence numerických hodnot v hexadecimálním formátu ; vstupy: ; HL - ukazatel na pole s hodnotami ; B - počet hodnot (délka pole) print_numbers: next_item: ld A, (HL) ; načíst hodnotu z pole inc HL ; přechod na další prvek pole call print_hex_number ; vytisknout hexa hodnotu ld A, B cp 1 ; za poslední hodnotou už nechceme tisknout mezeru jr Z, skip ; přeskočení tisku mezery u poslední hodnoty call space skip: djnz next_item ; zpracování dalšího prvku pole ret array1: db 0x00, 0x01, 0x05, 0x09, 0x09, 0x09, 0x10, 0x10, 0xa0, 0xfe, 0xff array2: db 0x01, 0x02, 0x05, 0x01, 0x06, 0x07, 0x09, 0x10, 0x01, 0x01, 0x01 print_hex_number: push AF ; uschovat A pro pozdější využití rrca ; rotace o čtyři bity doprava rrca rrca rrca and $0f ; zamaskovat horní čtyři bity call print_hex_digit; vytisknout hexa číslici pop AF ; obnovit A and $0f ; zamaskovat horní čtyři bity jp print_hex_digit ; vytisknout hexa číslici a návrat z podprogramu print_hex_digit: cp 0x0a ; test, jestli je číslice menší než 10 jr c, print_0_to_9 ; ok, hodnota je menší než 10, budeme tedy tisknout desítkovou číslici add A, 65-10-48 ; ASCII kód znaku 'A', ovšem začínáme od desítky, ne od nuly (+ update pro další ADD) print_0_to_9: add A, 48 ; ASCII kód znaku '0' rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku ret ; návrat ze subrutiny new_line: ld A, 0x0d ; kód znaku pro odřádkování rst 0x10 ; zavolání rutiny v ROM ret ; návrat ze subrutiny space: ld A, 32 ; kód mezery rst 0x10 ; zavolání rutiny v ROM ret ; návrat ze subrutiny end ENTRY_POINT
Překlad do strojového kódu bude vypadat takto:
ENTRY_POINT EQU 8000 ROM_CLS EQU 0DAF OUT_NUM_1 EQU 1A1B ORG 8000 8000: label start 8000:CDAF0D CALL 0DAF 8003:213E80 LD HL, 803E 8006:060B LD B, 0B 8008:CD2E80 CALL 802E 800B:214980 LD HL, 8049 800E:060B LD B, 0B 8010:CD2E80 CALL 802E 8013:CD6E80 CALL 806E 8016:CD6E80 CALL 806E 8019:113E80 LD DE, 803E 801C:214980 LD HL, 8049 801F:060B LD B, 0B 8021: label next_add 8021:1A LD A, (DE) 8022:86 ADD A, (HL) 8023:13 INC DE 8024:23 INC HL 8025:CD5480 CALL 8054 8028:CD7280 CALL 8072 802B:10F4 DJNZ 8021 802D:C9 RET 802E: label print_numbers 802E: label next_item 802E:7E LD A, (HL) 802F:23 INC HL 8030:CD5480 CALL 8054 8033:78 LD A, B 8034:FE01 CP 01 8036:2803 JR Z, 803B 8038:CD7280 CALL 8072 803B: label skip 803B:10F1 DJNZ 802E 803D:C9 RET 803E: label array1 803E:00010509 DEFB of 11 bytes 8042:09091010 8046:A0FEFF 8049: label array2 8049:01020501 DEFB of 11 bytes 804D:06070910 8051:010101 8054: label print_hex_number 8054:F5 PUSH AF 8055:0F RRCA 8056:0F RRCA 8057:0F RRCA 8058:0F RRCA 8059:E60F AND 0F 805B:CD6480 CALL 8064 805E:F1 POP AF 805F:E60F AND 0F 8061:C36480 JP 8064 8064: label print_hex_digit 8064:FE0A CP 0A 8066:3802 JR C, 806A 8068:C607 ADD A, 07 806A: label print_0_to_9 806A:C6e0 ADD A, 30 806C:D7 RST 10 806D:C9 RET 806E: label new_line 806E:3E0D LD A, 0D 8070:D7 RST 10 8071:C9 RET 8072: label space 8072:3E20 LD A, 20 8074:D7 RST 10 8075:C9 RET 8076: END 8000 Emiting TAP basic loader Emiting TAP from 8000 to 8075
10. Uložení numerických hodnot ve formátu BCD a Packed BCD
Ve druhé části dnešního článku se budeme zabývat uložením numerických hodnot ve formátu BCD; konkrétně nás bude zajímat varianta nazývaná Packed BCD. Zkratkou BCD neboli Binary-coded decimal se označuje skupina kódování numerických hodnot založená na jednoduchém principu – každá desítková číslice je uložena ve čtyřech bitech. Tyto čtyři bity jsou buď uloženy v samostatném bajtu (co bajt, to jediná číslice) nebo jsou vždy „dvojice čtveřic“ bitů uloženy do jediného bajtu. Druhý zmíněný formát se nazývá Packed BCD a v naprosté většině případů se jedná o variantu big endian (a to nezávisle na procesorové architektuře).
V případě, že je nutné pracovat například s hodnotami v rozsahu 0 až 99999, je nutné pro takové BCD hodnoty alokovat pro každou číslici čtyři bity a celkem je tedy minimálně nutné použít 5×4=20 bitů. Naproti tomu v případě použití binárního kódování je zapotřebí pouze sedmnácti bitů, protože 217=131072 > 99999.
BCD se v nejjednodušším případě používá pro uložení celých čísel, a to buď bez znaménka (jednotlivé cifry, jak již bylo naznačeno výše) nebo se znaménkem (potom je znaménko typicky uloženo ve vlastním bitu, nebo se navíc používá dvojkový doplněk, to ovšem méně často). Ovšem můžeme se setkat i s takzvaným FX formátem (fixed point), v němž je desetinná tečka umístěna za předem známou cifrou a je neměnná – počet cifer před desetinnou tečkou a za ní je stále stejný. To znamená, že se v takovém případě nemusí ukládat exponent, který u FP hodnot přímo či nepřímo určoval pozici řádové čárky v uloženém číslu.
11. Podpora pro výpočty v BCD v instrukčních sadách mikroprocesorů
Výpočty s číselnými hodnotami uloženými v kódu BCD se ve výpočetní technice používají již od první generace (elektronkových) mainframů, které společnost IBM vyráběla v padesátých letech minulého století. Dnes se s BCD setkáme například při programování mikrořadičů, protože některé sedmisegmentové LCD, čipy s hodinami reálného času či malé numerické klávesnice kód BCD používají. Ostatně i z tohoto důvodu výpočty v BCD podporuje většina mikrořadičů, s výjimkou některých řad osmibitových mikrořadičů PIC. Čipy podporující výpočty v BCD můžeme rozdělit do tří kategorií:
- Registry přímo obsahují BCD (typicky dvě číslice 00–99) a ALU taktéž produkuje výsledek v BCD. Typickým příkladem je slavný osmibitový mikroprocesor MOS 6502, který lze přepnout do „dekadického režimu“ instrukcí SED (Set Decimal Mode) či se přepnout zpátky instrukcí CLD (Clear Decimal Mode).
- ALU sice provádí výpočty v binárním kódu, ale po provedení výpočtu je možné explicitně provést úpravu výsledku na BCD (na základě nastavených příznaků přenosu a polovičního přenosu). Typickým příkladem jsou čipy Intel 8048, Intel 8051, Motorola 6809, Motorola 68HC11 atd. atd. s instrukcí DAA či DA A používanou po operaci součtu a rozdílu. Podobná je instrukce A6AAC u čtyřbitových mikrořadičů TMS-1000. S tímto konceptem se blíže seznámíme v dalších kapitolách.
- ALU provádí většinu operací v binárním režimu, ovšem některé instrukce ji mohou přepnout do režimu BCD. Příkladem je Motorola 68000 s instrukcemi ABCD (Add Binary Coded Decimal), NBCD (Negate Binary Coded Decimal) a SBCD (Subtract Binary Coded Decimal).
Obrázek 8: Jedna z typických nasazení čtyřbitových mikrořadičů – nejjednodušší kalkulačky .
Některé mikroprocesory obsahují větší množství instrukcí pro úpravu výsledku a/nebo vstupních operandů. Příkladem může být čip 8086 (s instrukční sadou udržovanou dodnes), podporující jak „packed BCD“ (dvě cifry v bajtu), tak i „unpacked BCD“ (jediná cifra v bajtu). V instrukční sadě nalezneme hned šest relevantních instrukcí:
Operace | Packed BCD | Unpacked BCD |
---|---|---|
součet | DAA | AAA |
rozdíl | DAS | AAS |
součin | × | AAM |
podíl | × | AAD |
BCD používá i matematický koprocesor x86 (konkrétně čip 8087 a kvůli zpětné kompatibilitě i dnešní CPU+FPU), který dokáže do osmdesáti bitového slova uložit 18 BCD cifer + znaménko (necelé dva bajty se přitom nevyužijí).
Obrázek 9: Segmentem, v němž se BCD používá dodnes, jsou kalkulačky.
12. Příznak half carry a instrukce DAA
V souvislosti s formátem Packed BCD je nutné, aby mikroprocesor při provádění aritmetických operací dokázal výsledky upravit takovým způsobem, aby výsledkem byla opět hodnota s formátem Packed BCD. V praxi to v tom nejjednodušším případě znamená, že k výsledné cifře je nutné při přetečení přes 4 bity připočíst hodnotu 6. A vzhledem k tomu, že v bajtu jsou uloženy dvě BCD cifry, znamená to:
- Je nutné detekovat přetečení/přenos z bitů 0–3 do bitu 4 (dolní BCD cifra)
- Je nutné detekovat přetečení/přenos z bitu 7 (horní BCD cifra)
Výsledná hodnota se tedy bude měnit následovně:
- +0×00 pokud nedošlo k přetečení
- +0×06 pokud došlo k prvnímu typu přetečení
- +0×60 pokud došlo ke druhém typu přetečení
- +0×66 pokud došlo k obou přetečením
O výše uvedené úpravy výsledku se stará instrukce DAA (Decimal Add Adjust). V mnoha ohledech se jedná o nejsložitější instrukci mikroprocesoru Zilog Z80, neboť její chování závisí na mnoha vstupních hodnotách.
13. Vliv příznaků a hodnoty v akumulátoru na operaci DAA
V následující tabulce je ukázáno, jaká hodnota se přičte k výsledku poslední „sčítací“ operace typu ADD, ADC a INC na základě příznaků C a H a taktéž na základě hodnoty uložené v akumulátoru. Povšimněte si, že se skutečně provádí přičtení konstant 00, 6, 60 nebo 66:
C před DAA | Horní cifra | H před DAA | Dolní cifra | Přičítaná hodnota | C po DAA |
---|---|---|---|---|---|
0 | 0–9 | 0 | 0–9 | 00 | 0 |
0 | 0–8 | 0 | A-F | 06 | 0 |
0 | 0–9 | 1 | 0–3 | 06 | 0 |
0 | A-F | 0 | 0–9 | 60 | 1 |
0 | 9-F | 0 | A-F | 66 | 1 |
0 | A-F | 1 | 0–3 | 66 | 1 |
1 | 0–2 | 0 | 0–9 | 60 | 1 |
1 | 0–2 | 0 | A-F | 66 | 1 |
1 | 0–3 | 1 | 0–3 | 66 | 1 |
Druhá tabulka platí pro „odečítací“ operace typu SUB, SBC, DEC a kupodivu taktéž NEG:
C před DAA | Horní cifra | H před DAA | Dolní cifra | Přičítaná hodnota | C po DAA |
---|---|---|---|---|---|
0 | 0–9 | 0 | 0–9 | 00 | 0 |
0 | 0–8 | 1 | 6-F | FA | 0 |
1 | 7-F | 0 | 0–9 | A0 | 1 |
1 | 6-F | 1 | 6-F | 9A | 1 |
14. Realizace součtu dvou numerických hodnot uložených ve formátu Packed BCD
Součet dvou numerických hodnot reprezentovaných ve formátu Packed BCD je triviální – pouze musíme za instrukci součtu doplnit instrukci DAA, která výsledek součtu opraví tak, aby se opět jednalo o BCD číslice:
ld A, (DE) ; načíst první sčítanec z pole add A, (HL) ; načíst druhý sčítanec z pole daa ; provést decimální korekci
Tuto trojici instrukcí použijeme v dnešním posledním demonstračním příkladu.
15. Tisk tabulky se sčítanci i součty
Předchozí demonstrační příklad, který vytisknul tabulku s výsledky součtů binárně uložených hodnot můžeme triviálním způsobem upravit tak, aby se výpočty prováděly s BCD hodnotami, přičemž výsledkem bude pochopitelně opět BCD hodnota. Nejprve si necháme opět vytisknout hodnoty sčítanců (vždy dva sčítance použité v jedné operaci pod sebou):
start: call ROM_CLS ; smazání obrazovky a otevření kanálu číslo 2 (screen) ld HL, array1 ; vytištění 11 hodnot z pole array1 v hexadecimálním formátu ld B, 11 call print_numbers ld HL, array2 ; vytištění 11 hodnot z pole array2 v hexadecimálním formátu ld B, 11 call print_numbers
Vložíme prázdný řádek (ovšem popravdě řečeno mi není jasné, proč se příslušná subrutina musí volat dvakrát, pokud je kurzor za koncem řádku):
call new_line ; odřádkování call new_line ; (chyba v ROM subrutině nebo užitečná vlastnost?)
A dále vytiskneme výsledek součtu prováděného s BCD hodnotami. Povšimněte si, že po operaci ADD je vložena instrukce DAA, která výsledek opraví do korektního BCD tvaru (pokud je to ovšem možné):
ld DE, array1 ; adresa pole s první řadou sčítanců ld HL, array2 ; adresa pole se druhou řadou sčítanců ld B, 11 next_add: ld A, (DE) ; načíst první sčítanec z pole add A, (HL) ; načíst druhý sčítanec z pole daa ; provést decimální korekci inc DE ; posun ukazatele na další sčítanec inc HL ; dtto call print_hex_number ; vytisknout hexa hodnotu výsledku call space djnz next_add ; kontrola počtu zobrazených výsledků ret
A takto by měla vypadat obrazovka po dokončení běhu programu:
Obrázek 10: Tabulka se součty dvojic hodnot uložených ve formátu Packed BCD.
Výsledky můžeme rozdělit do tří kategorií:
- Korektní výsledek pro korektní vstup (modrý obdélník)
- Nekorektní výsledek pro nekorektní vstup (červený obdélník)
- Přetečení výsledku pro hodnotu přesahující 99
Obrázek 11: Modře jsou vybarveny výpočty se skutečnými hodnotami Packed BCD, červeně pak výsledky, které nejsou korektní kvůli odlišnému vstupu.
16. Úplný zdrojový kód dnešního pátého demonstračního příkladu
Úplný zdrojový kód demonstračního příkladu popsaného v předchozích dvou kapitolách je dostupný na adrese https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/78-add-bcd-numbers.asm:
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 HL, array1 ; vytištění 11 hodnot z pole array1 v hexadecimálním formátu ld B, 11 call print_numbers ld HL, array2 ; vytištění 11 hodnot z pole array2 v hexadecimálním formátu ld B, 11 call print_numbers call new_line ; odřádkování call new_line ; (chyba v ROM subrutině nebo užitečná vlastnost?) ld DE, array1 ; adresa pole s první řadou sčítanců ld HL, array2 ; adresa pole se druhou řadou sčítanců ld B, 11 next_add: ld A, (DE) ; načíst první sčítanec z pole add A, (HL) ; načíst druhý sčítanec z pole daa ; provést decimální korekci inc DE ; posun ukazatele na další sčítanec inc HL ; dtto call print_hex_number ; vytisknout hexa hodnotu výsledku call space djnz next_add ; kontrola počtu zobrazených výsledků ret ; podprogram pro tisk sekvence numerických hodnot v hexadecimálním formátu ; vstupy: ; HL - ukazatel na pole s hodnotami ; B - počet hodnot (délka pole) print_numbers: next_item: ld A, (HL) ; načíst hodnotu z pole inc HL ; přechod na další prvek pole call print_hex_number ; vytisknout hexa hodnotu ld A, B cp 1 ; za poslední hodnotou už nechceme tisknout mezeru jr Z, skip ; přeskočení tisku mezery u poslední hodnoty call space skip: djnz next_item ; zpracování dalšího prvku pole ret array1: db 0x00, 0x01, 0x05, 0x09, 0x09, 0x09, 0x10, 0x10, 0xa0, 0xfe, 0xff array2: db 0x01, 0x02, 0x05, 0x01, 0x06, 0x07, 0x09, 0x10, 0x01, 0x01, 0x01 print_hex_number: push AF ; uschovat A pro pozdější využití rrca ; rotace o čtyři bity doprava rrca rrca rrca and $0f ; zamaskovat horní čtyři bity call print_hex_digit; vytisknout hexa číslici pop AF ; obnovit A and $0f ; zamaskovat horní čtyři bity jp print_hex_digit ; vytisknout hexa číslici a návrat z podprogramu print_hex_digit: cp 0x0a ; test, jestli je číslice menší než 10 jr c, print_0_to_9 ; ok, hodnota je menší než 10, budeme tedy tisknout desítkovou číslici add A, 65-10-48 ; ASCII kód znaku 'A', ovšem začínáme od desítky, ne od nuly (+ update pro další ADD) print_0_to_9: add A, 48 ; ASCII kód znaku '0' rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku ret ; návrat ze subrutiny new_line: ld A, 0x0d ; kód znaku pro odřádkování rst 0x10 ; zavolání rutiny v ROM ret ; návrat ze subrutiny space: ld A, 32 ; kód mezery rst 0x10 ; zavolání rutiny v ROM ret ; návrat ze subrutiny end ENTRY_POINT
Pro úplnost si ukažme způsob překladu tohoto demonstračního příkladu do assembleru:
ENTRY_POINT EQU 8000 ROM_CLS EQU 0DAF OUT_NUM_1 EQU 1A1B ORG 8000 8000: label start 8000:CDAF0D CALL 0DAF 8003:213F80 LD HL, 803F 8006:060B LD B, 0B 8008:CD2F80 CALL 802F 800B:214A80 LD HL, 804A 800E:060B LD B, 0B 8010:CD2F80 CALL 802F 8013:CD6F80 CALL 806F 8016:CD6F80 CALL 806F 8019:113F80 LD DE, 803F 801C:214A80 LD HL, 804A 801F:060B LD B, 0B 8021: label next_add 8021:1A LD A, (DE) 8022:86 ADD A, (HL) 8023:27 DAA 8024:13 INC DE 8025:23 INC HL 8026:CD5580 CALL 8055 8029:CD7380 CALL 8073 802C:10F3 DJNZ 8021 802E:C9 RET 802F: label print_numbers 802F: label next_item 802F:7E LD A, (HL) 8030:23 INC HL 8031:CD5580 CALL 8055 8034:78 LD A, B 8035:FE01 CP 01 8037:2803 JR Z, 803C 8039:CD7380 CALL 8073 803C: label skip 803C:10F1 DJNZ 802F 803E:C9 RET 803F: label array1 803F:00010509 DEFB of 11 bytes 8043:09091010 8047:A0FEFF 804A: label array2 804A:01020501 DEFB of 11 bytes 804E:06070910 8052:010101 8055: label print_hex_number 8055:F5 PUSH AF 8056:0F RRCA 8057:0F RRCA 8058:0F RRCA 8059:0F RRCA 805A:E60F AND 0F 805C:CD6580 CALL 8065 805F:F1 POP AF 8060:E60F AND 0F 8062:C36580 JP 8065 8065: label print_hex_digit 8065:FE0A CP 0A 8067:3802 JR C, 806B 8069:C607 ADD A, 07 806B: label print_0_to_9 806B:C630 ADD A, 30 806D:D7 RST 10 806E:C9 RET 806F: label new_line 806F:3E0D LD A, 0D 8071:D7 RST 10 8072:C9 RET 8073: label space 8073:3E20 LD A, 20 8075:D7 RST 10 8076:C9 RET 8077: END 8000 Emiting TAP basic loader Emiting TAP from 8000 to 8076
17. Obsah následujícího článku
V navazujícím článku si nejprve ukážeme trik pro tisk hexadecimálních hodnot. Tento trik je založen na instrukci DAA a osmibitové aritmetice. A posléze se zaměříme na zcela odlišnou oblast – jak se dá pracovat s numerickými hodnotami reprezentovanými v systému pevné i plovoucí řádové tečky (fixed point, floating point).
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 osmi článcích [1] [2], [3], [4], [5], [6], [7], [8], 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 73.tap 74.tap 75.tap 76.tap 77.tap 78.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 73.tap: 73-print-flags-7.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 73-print-flags-7.lst 74.tap: 74-print-hex-number.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 74-print-hex-number.lst 75.tap: 75-print-hex-number.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 75-print-hex-number.lst 76.tap: 76-print-hex-numbers.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 76-print-hex-numbers.lst 77.tap: 77-add-hex-numbers.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 77-add-hex-numbers.lst 78.tap: 78-add-bcd-numbers.asm $(ASSEMBLER) -v -d --tapbas $< $@ > 78-add-bcd-numbers.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 |
74 | 74-print-hex-number.asm | tisk hexadecimálního čísla v rozsahu 0×00 až 0×ff (neoptimalizovaná varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/74-print-hex-number.asm |
75 | 75-print-hex-number.asm | tisk hexadecimálního čísla v rozsahu 0×00 až 0×ff (optimalizovaná varianta) | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/75-print-hex-number.asm |
76 | 76-print-hex-numbers.asm | tisk několika hexadecimálních hodnot | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/76-print-hex-numbers.asm |
77 | 77-add-hex-numbers.asm | součet dvou osmibitových hexadecimálních hodnot s tiskem všech výsledků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/77-add-hex-numbers.asm |
78 | 78-add-bcd-numbers.asm | součet dvou osmibitových BCD hodnot s tiskem všech výsledků | https://github.com/tisnik/8bit-fame/blob/master/Speccy-asm/78-add-bcd-numbers.asm |
79 | 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 - Extended Binary Coded Decimal Interchange Code
http://en.wikipedia.org/wiki/EBCDIC - ASCII/EBCDIC Conversion Table
http://docs.hp.com/en/32212–90008/apcs01.html - EBCDIC
http://www.hansenb.pdx.edu/DMKB/dict/tutorials/ebcdic.php - EBCDIC tables
http://home.mnet-online.de/wzwz.de/temp/ebcdic/cc_en.htm - The Mainframe Blog
http://mainframe.typepad.com/blog/2006/11/my_personal_mai.html - Binary-coded decimal
https://en.wikipedia.org/wiki/Binary-coded_decimal - BCD
https://cs.wikipedia.org/wiki/BCD