Grafická karta Hercules: úspěšná alternativa a konkurence MDA i CGA

18. 7. 2024
Doba čtení: 37 minut

Sdílet

 Autor: Pavel Tišnovský
Alternativou ke grafickým kartám MDA a CGA se v roce 1983 stala karta Hercules. Nabízela stejně dobré rozlišení textového režimu jako karta MDA a navíc podporovala i monochromatický grafický režim 720×348 pixelů.

Obsah

1. Grafická karta Hercules: úspěšná alternativa a konkurence MDA i CGA

2. Plná kompatibilita s MDA

3. Základní technické parametry karty Hercules

4. Textový režim karty Hercules

5. První demonstrační příklad: zobrazení textu s atributy kartou Hercules

6. Řídicí registry karty Hercules dostupné přes I/O porty

7. Vypnutí blikání textu, pokud je nejvyšší atributový bit nastavený na jedničku

8. Úplný zdrojový kód dnešního druhého demonstračního příkladu

9. Zákaz generování video signálu

10. Úplný zdrojový kód dnešního třetího demonstračního příkladu

11. Grafický režim karty Hercules

12. Postup pro přepnutí do grafického režimu

13. Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu

14. Vylepšení kódu: efektivnější zápis do registrů CRTC

15. Úplný zdrojový kód dnešního pátého demonstračního příkladu

16. Postup při vykreslení jednoho pixelu v grafickém režimu karty Hercules

17. Předpočet adres jednotlivých obrazových řádků

18. Úplný zdrojový kód dnešního šestého demonstračního příkladu

19. Repositář s demonstračními příklady

20. Odkazy na Internetu

1. Grafická karta Hercules: úspěšná alternativa a konkurence MDA i CGA

Obě grafické karty vydané v roce 1981 společností IBM k jejich počítači IBM PC, tj. jak karty MDA, tak i CGA, mají i přes mnohé rozdíly několik společných vlastností. Jedná se totiž v obou případech o karty navržené a prodávané (opět: již od roku 1981) firmou IBM, které jsou vybavené rozhraním pro osmibitovou variantu universální interní sběrnice ISA (Industry Standard Architecture). Obě karty jsou taktéž založeny na již popsaném grafickém řadiči Motorola MC6845, což by sice na první pohled mohlo znamenat určitou míru kompatibility, ale přesný opak byl pravdou – firma IBM u obou karet zvolila odlišné řádkové frekvence (konkrétně 18,432 kHz u karty MDA a nižší frekvenci 15,75 kHz u karty CGA) i jiný typ videosignálů, což ve výsledku vedlo k tomu, že pro každou kartu musel být použitý odlišný monitor (navíc CGA podporovala jak „digitální“ RGBI monitory, tak i monitory akceptující kompozitní video signál).

pc84

Obrázek 1: Slavný tuzemský textový editor T602 spuštěný na počítači s grafickou kartou Hercules (viz navazující kapitoly).

Zatímco grafická karta CGA nabízela možnost barevného zobrazení (viz též předchozí tři články, v nichž jsme se touto kartou podrobně zabývali) na úkor menšího – pro mnohé uživatele zcela neakceptovatelného – horizontálního i vertikálního zobrazení, umožňovala sice karta MDA zobrazení velmi dobře čitelného textu, ovšem bez možnosti použití jakéhokoli grafického režimu (pochopitelně až na pseudorežim založený na znacích z rozšířené ASCII).

pc84

Obrázek 2: T602 zobrazený kartou CGA (skutečný obraz má ve skutečnosti jen 200 obrazových řádků, nikoli 400, ty byly uměle zvětšeny emulátorem).

V této situaci se, pravděpodobně vůbec poprvé (z hlediska koncového uživatele), projevila jedna z největších předností architektury IBM PC – modularita. Zatímco firma IBM vlastně nijak nereagovala na oprávněné výtky, které od uživatelů přicházely především kvůli vlastnostem grafické karty CGA (i mnohé osmibitové počítače totiž měly grafický subsystém vyřešený mnohem elegantněji), objevil se v roce 1982 konkurenční výrobek – grafická karta Hercules Graphics Card (HGC) firmy Hercules Computer Technology. A i přesto, že Hercules nikdy nebyl podporován v BIOSu, stal se velmi populární alternativou a začal být podporován i velkými výrobci SW.

pc84

Obrázek 3: T602 zobrazený kartou EGA v rozlišení 640×350 v šestnácti barvách (touto kartou se budeme zabývat příště).

2. Plná kompatibilita s CGA

Výrobce grafickou kartu Hercules navrhl takovým způsobem, aby ji bylo možné použít s monitorem určeným pro kartu MDA, ovšem včetně možnosti přepnutí do monochromatického grafického režimu s relativně vysokým rozlišením 720×348 pixelů (což je na dobu vzniku velmi slušné a dosti to konkurovalo například pozdějšímu Atari ST s monochromatickým monitorem a rozlišením 640×400 pixelů – oba typy počítačů se v takové konfiguraci používaly ve firmách pro „seriózní práci“, ne na hraní her). Dodržení zpětné kompatibility s kartou MDA nebylo složité – v textovém i grafickém režimu (viz další text) byly použity takové frekvence synchronizačních signálů (řádková a snímková frekvence), která odpovídaly signálům generovaným kartou MDA.

pc84

Obrázek 4: Textový editor T602 zobrazený poměrně neznámou kartou MCGA, která v režimu nejvyššího rozlišení 640×480 měla jen jednu bitovou rovinu a tím pádem podporovala pouze dvě barvy (ovšem na druhou stranu s poměrně slušným rozlišením).

I způsob práce Herculesu v textovém režimu se od karty MDA téměř nelišil, což znamenalo, že na této kartě bylo možné provozovat všechny aplikace pracující v textovém režimu (navíc bylo možné s využitím rezidentních programů simulovat i grafické režimy karty CGA, přičemž se jednotlivé barevné odstíny nahrazovaly ditheringem). Především z těchto důvodů byla grafická karta Hercules v první polovině osmdesátých let minulého století velmi oblíbená a do svých sestav ji instalovali i tehdejší přední výrobci osobních počítačů. K velké oblíbenosti přispěla i poměrně nízká cena, takže se karta Hercules používala i v době nástupu grafické karty EGA, jejímž popisem se ovšem dnes zabývat nebudeme (i když čip 6845 velmi zdárně emulovala!).

pc84

Obrázek 5: Nejlepší rozlišení i největší počet barev pro textový editor T602 nabízela grafická karta VGA – 640×480 pixelů v šestnácti barvách (editor však využil jen podmnožinu barvové palety, navíc obrazová frekvence nebyla nijak ohromující).

Firma Hercules Computer Technology vytvořila i následníka této grafické karty – Hercules Plus – jenž se odlišoval především v tom, že bylo možné programově měnit znakovou sadu v textovém režimu a docílit tak například zobrazení českých znaků (u původního Herculesu či MDA se znaková sada měnila přeprogramováním paměti EPROM).

3. Základní technické parametry karty Hercules

Grafická karta Hercules je založena, podobně jako oba již popsané grafické adaptéry firmy IBM, na čipu Motorola MC6845, nebo (konkrétně v případě různých klonů) na VLSI obvodu se stejnými vlastnostmi i významem řídicích portů. Jak bude z dalšího popisu patrné, je čip MC6845 v této kartě zapojen a naprogramován poněkud odlišným způsobem než tomu bylo u grafické karty CGAMDA. Kartu Hercules lze připojit do standardní osmibitové sběrnice ISA (v dokumentaci firmy IBM také označované termínem PC-BUS), přičemž se předpokládalo, že frekvence hodinových signálů této sběrnice bude rovna 4,77 MHz (frekvence základního oscilátoru 14,285 MHz je při generování hodinových signálů dělená třemi). Modernější osobní počítače měly frekvenci hodinových signálů sběrnice ISA zvýšenou na 8, 8.33, 10 či 12 MHz, ovšem při takto vysokých frekvencích mohlo na kartě Hercules docházet k výpadkům dat při zápisu do video paměti.

Na grafické kartě byl kromě řadiče, podpůrných obvodů a video paměti přítomný i jeden paralelní port, což také přispívalo k oblíbenosti Herculesu mezi zákazníky, protože první personální počítače typu IBM PC tyto porty neměly nainstalovány přímo na základní desce a bylo je zapotřebí zvlášť dokupovat (a tím mimo jiné přicházet o jednu pozici na ISA sběrnici, nehledě na relativně vysokou cenu jakýchkoli PC komponent; v případě Herculesu zákazníci měli paralelní port „zdarma“).

Poznámka: to platí pro originální Herculesy, ne pro jejich více či méně oficiální klony, které se objevily záhy po vydání této karty.

Kapacita obrazové paměti byla oproti kartě CGA zvýšena na dvojnásobek, tj. na celých 32 kB. Kromě paměťových modulů tvořících obrazovou paměť byla na kartě nainstalována i paměť typu ROM, popř. EPROM, ve které byla uložena znaková sada, konkrétně bitové podoby znaků (viz další kapitolu). Ovládání grafického čipu bylo prováděno s využitím parametrů ukládaných přes vstupně/výstupní porty umístěné na adresách 0×3b00×3bf, přičemž na adresy 0×3b4 a 0×3b5 byly namapovány řídicí registry čipu MC6845 (těchto registrů je, jak již víme z předchozích kapitol, celkem osmnáct, ovšem poslední dva registry týkající se světelného pera lze ignorovat). Vhodnou změnou parametrů docházelo k přepínání mezi textovým a grafickým režimem, bylo však možné také měnit parametry zobrazení grafiky (rozlišení, zpoždění synchronizačních signálů, pozice hardwarového textového kurzoru, mikroposun textových řádků apod.), čehož se často používalo při emulaci grafických režimů karty CGA. Některé tyto možnosti si ještě ukážeme v dalším textu.

Čtením stavových bitů z portu 0×3ba bylo možné testovat průběh horizontálního i vertikálního zatemnění (synchronizace používaná například ve hrách) a číst polohu hrotu světelného pera. Vzhledem k tomu, že grafická paměť byla z hlediska mikroprocesoru mapována od adresy b000:0000 do adresy b000:7fff (opět je použit způsob adresování segment:offset), nedocházelo k překryvu s obrazovou pamětí grafické karty CGA a proto lze tyto dvě karty provozovat současně i na jednom počítači (ovšem i toto bylo konfigurovatelné, takže paměť mohla být mapována jak do segmentu 0×b000, tak i do segmentu 0×b800).

Taktéž nedochází k překryvům vstupně/výstupních portů, neboť ty jsou v případě karty CGA umístěny o 16 bajtů výše. Hercules je v případě použití této kombinace využit pro kvalitní zobrazování textu a monochromatické grafiky, CGA pro zobrazení barevné (ehm :-) grafiky. Další poměrně oblíbenou kombinací z pozdější doby byla VGA+Hercules, ovšem v tomto případě Hercules většinou sloužil pro práci v textovém režimu (čehož dokázaly využít IDE firmy Borland, AutoCAD atd.).

4. Textový režim karty Hercules

V×textovém režimu je grafická karta Hercules prakticky stoprocentně kompatibilní s kartou MDA, tj. pracuje se s textem o 80 sloupcích a 25 řádcích, včetně stejného způsobu práce s atributy jednotlivých znaků (podtržení apod.). Text je zobrazován v rozlišení 720 350 pixelů, což umožňuje na jeden znak použít masku o velikosti 9×14 pixelů. Textovou obrazovku lze mapovat buď od adresy b000:0000 nebo od adresy b800:0000. Jedinou nevýhodou textového režimu grafické karty Hercules je fakt, že znaková sada je uložena v paměti EPROM typu 27C64 a nelze ji tedy programově změnit, pouze „přepálit“ (pro zajímavost – všechny Herculesy s „přepálenou“ znakovou sadou, které jsem viděl, používaly kódování Kamenických, viz další odstavec). Tvary znaků jsou v paměti EPROM uloženy tak, jakoby jejich maska měla velikost 8×16 pixelů, avšak pro každý znak se při jeho vykreslování dva řádky ignorují a podle pozice znaku v ASCII tabulce se doplňuje devátý sloupec pixelů, čímž se dostáváme k výsledné masce 9×14 pixelů (devátý sloupec vzniká kopií osmého sloupce u znaků představujících rámečky, jinak je tento sloupec vždy prázdný).

Obrázek 6: Volkov Commander v režimu karty Hercules.

Z výše uvedených informací vyplývá, že pro uložení celé znakové sady by měly dostačovat pouhé čtyři kilobajty, neboť 16 řádků×1 bajt×256 znaků=4096 bajtů. Ovšem vzhledem k tomu, že paměť EPROM 27C64 má kapacitu 8 kB, jsou horní 4 kB nevyužity. Vhodnou hardwarovou úpravou je však možné implementovat dvě znakové sady – u nás se většinou používala originální sada US-ASCII a již zmíněné české znaky v kódu Kamenických. Kromě původní karty Hercules se vyráběla taktéž již zmíněná karta Hercules Plus, která se od původního modelu odlišuje především v tom, že znakovou sadu ukládá do paměti typu (D)RAM a umožňuje tak programově měnit používanou znakovou sadu. U této karty je dokonce možné rozšířit počet znaků ve znakové sadě až na teoretickou hodnotu 212=4096 tím způsobem, že se čtyři bity v atributovém bajtu použijí na definici atributů znaků a zbylé čtyři bity se připojí k osmibitovému ASCII kódu znaku. Ne všechny kódy však mohou být skutečně využity, protože velikost paměti vyhrazené pro znakovou sadu dosahuje 48 kB a ne 64 kB.

Obrázek 7: QBasic v režimu karty Hercules.

5. První demonstrační příklad: zobrazení textu s atributy kartou Hercules

Dnešní první demonstrační příklad je velmi jednoduchý. Ukážeme si v něm vykreslení sady znaků společně s jejich atributy (popředí/pozadí) a porovnáme výsledek získaný na kartě CGA a Herculesu. Nesmíme pouze zapomenout, že na kartě CGA leží textová paměť v segmentu 0×b800, zatímco u Herculesu je to segment 0×b000:

        mov ax, 0xb000
        mov es, ax
        mov di, 0       ; nyni ES:DI obsahuje adresu prvniho znaku ve video RAM

Výsledek pro kartu CGA:

Obrázek 8: Text s atributy vykreslený kartou CGA.

Pro počítač s Herculesem získáme mnohem čitelnější text, ovšem (podle očekávání) pouze monochromatický:

Obrázek 9: Text s atributy vykreslený kartou Hercules.

A takto vypadá úplný zdrojový kód dnešního prvního demonstračního příkladu:

; Textovy rezim karty Hercules s rozlisenim 80x25 znaku.
;
; preklad pomoci:
;     nasm -f bin -o hercules.com hercules_text_mode_1.asm
;
; nebo pouze:
;     nasm -o hercules.com hercules_text_mode_1.asm
 
 
;-----------------------------------------------------------------------------
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        mov ax, 0xb000
        mov es, ax
        mov di, 0       ; nyni ES:DI obsahuje adresu prvniho znaku ve video RAM
 
        mov cx, 80*25   ; pocet zapisovanych znaku
        mov al, 0       ; kod zapisovaneho znaku
opak:
        stosb           ; zapis znaku + atributu
        stosb
        inc al          ; dalsi znak/atribut
        loop opak       ; opakujeme CX-krat
 
        wait_key
        exit

6. Řídicí registry karty Hercules dostupné přes I/O porty

Grafická karta Hercules obsahuje sedm řídicích a stavových registrů (k nimž ovšem můžeme připočítat i registry pro paralelní port). Povšimněte si, že I/O porty těchto registrů se liší od karty CGA, což umožňuje současnou instalaci obou karet:

Port Význam
3b4 výběr registru CRTC pro zápis nebo čtení
3b5 po výběru CRTC registru se odtud provede zápis či čtení
3b8 volba textového/grafického režimu, povolení blikání a video signálu
3b9 latch (záchytný registr) světelného pera
3ba stavový registr (aktivní VSync, HSync apod.)
3bb latch (záchytný registr) světelného pera
3bf ochrana před přepnutím do grafického režimu

První dva I/O porty již známe z popisu karty CGA a ještě se k nim vrátíme v navazujících kapitolách. Ovšem nejdůležitější je port 3b8, jehož jednotlivé bity mají následující význam:

Bit Význam
0 ×
1 0-textový režim, 1-grafický režim
2 ×
3 0-paprsek vypnutý, 1-zobrazování
4 ×
5 0-zákaz blikání pozadí, 1-povolení blikání pozadí (nejvyšší bit atributu)
6 ×
7 0-video RAM je mapována do segmentu 0×b000, 1-video RAM je mapována do segmentu 0b800
Poznámka: ovšem v žádném případě nedostačuje nastavit bit číslo 1 na jedničku a doufat, že se Hercules přepne do grafického režimu. Ve skutečnosti je nutné přeprogramovat i registry CRTC.

7. Vypnutí blikání textu, pokud je nejvyšší atributový bit nastavený na jedničku

Řídicí registr grafické karty Hercules je dostupný na I/O portu 0×3b8, takže si v assembleru vytvoříme symbolické jméno tohoto registru:

hercules_control  equ 0x3b8

Pro nastavení jednotlivých bitů tohoto registru použijeme nové makro, které vypadá (a i se tak používá) naprosto triviálně:

; nastaveni ridiciho registru
%macro set_control 1
        mov dx, hercules_control
        mov al, %1    ; ridici registr
        out dx, al
%endmacro

Nyní již můžeme zakázat blikání textu, a to zápisem hodnoty 0×08 neboli 0b00001000:

Bit Význam
0 0
1 0-textový režim
2 0
3 1-zobrazování
4 0
5 0-zákaz blikání pozadí
6 0
7 0-video RAM je mapována do segmentu 0×b000

Samotný zápis:

        set_control 0x08 ; zakaz blikani

Výsledná textová obrazovka by měla vypadat následovně:

Obrázek 10: Obrazovka se zakázaným blikáním textu.

8. Úplný zdrojový kód dnešního druhého demonstračního příkladu

Úplný zdrojový kód druhého demonstračního příkladu, který modifikuje způsob zobrazení textu (v textovém režimu) vypadá následovně:

; Textovy rezim karty Hercules s rozlisenim 80x25 znaku.
; Zmena zpusobu interpretace sedmeho bitu atributu.
;
; preklad pomoci:
;     nasm -f bin -o hercules.com hercules_text_mode_2.asm
;
; nebo pouze:
;     nasm -o hercules.com hercules_text_mode_2.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty Hercules
hercules_index    equ 0x3b4
hercules_control  equ 0x3b8
hercules_status   equ 0x3ba
hercules_config   equ 0x3bf
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
 
; nastaveni ridiciho registru
%macro set_control 1
        mov dx, hercules_control
        mov al, %1    ; ridici registr
        out dx, al
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        mov ax, 0xb000
        mov es, ax
        mov di, 0       ; nyni ES:DI obsahuje adresu prvniho znaku ve video RAM
 
        mov cx, 80*25   ; pocet zapisovanych znaku
        mov al, 0       ; kod zapisovaneho znaku
opak:
        stosb           ; zapis znaku + atributu
        stosb
        inc al          ; dalsi znak/atribut
        loop opak       ; opakujeme CX-krat
 
        wait_key
 
        set_control 0x08 ; zakaz blikani
 
        wait_key
        exit

9. Zákaz generování video signálu

Pro zajímavost se pokusme zakázat generování video signálu. Na skutečné kartě Hercules by měla obrazovka zčernat (nebo zmodrat, v závislosti na jejím typu), ovšem DOSBox – zdá se – bit pro zákaz zobrazování ignoruje:

        set_control 0x00 ; zakaz zobrazeni
Poznámka: nicméně v dalších demonstračních příkladech budeme video signál i tak vypínat, a to konkrétně při přepínání z textového režimu do režimu grafického. Výsledné programy tak budou kompatibilní s reálným HW.

10. Úplný zdrojový kód dnešního třetího demonstračního příkladu

Opět se podívejme na úplný zdrojový kód dnešního třetího demonstračního příkladu:

; Textovy rezim karty Hercules s rozlisenim 80x25 znaku.
; Vypnuti video signalu.
;
; preklad pomoci:
;     nasm -f bin -o hercules.com hercules_turn_off.asm
;
; nebo pouze:
;     nasm -o hercules.com hercules_turn_off.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty Hercules
hercules_index    equ 0x3b4
hercules_control  equ 0x3b8
hercules_status   equ 0x3ba
hercules_config   equ 0x3bf
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
 
; nastaveni ridiciho registru
%macro set_control 1
        mov dx, hercules_control
        mov al, %1    ; ridici registr
        out dx, al
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        mov ax, 0xb000
        mov es, ax
        mov di, 0       ; nyni ES:DI obsahuje adresu prvniho znaku ve video RAM
 
        mov cx, 80*25   ; pocet zapisovanych znaku
        mov al, 0       ; kod zapisovaneho znaku
opak:
        stosb           ; zapis znaku + atributu
        stosb
        inc al          ; dalsi znak/atribut
        loop opak       ; opakujeme CX-krat
 
        wait_key
 
        set_control 0x00 ; zakaz zobrazeni
 
        wait_key
        exit

11. Grafický režim karty Hercules

Grafický režim karty Hercules je, ostatně jako téměř ve všech obdobných případech, mnohem zajímavější a flexibilnější, než režim textový. Hercules podporoval na svou dobu poměrně vysoké rozlišení 720×348 obrazových bodů zobrazovaných černobíle nebo dvoubarevně. Konkrétní barvy použité při zobrazování byly závislé na typu obrazovky monitoru; kromě obligátní kombinace černá+zelená byla mezi výrobci obrazovek oblíbená například kombinace tmavě modrá a světle červená nebo tmavě modrá a žlutá (je to možná zvláštní kombinace, ovšem právě s tou jsme se mohli v tuzemsku setkat poměrně často).

Horizontální rozlišení grafického režimu je stejné, jako v případě režimu textového, protože platí 80 znaků na řádku × 9 horizontálních pixelů na znak = 720 pixelů. Vertikální rozlišení se však liší o dva skenovací řádky. V textovém režimu je vertikální rozlišení, tj. počet obrazových řádků, rovno 350 pixelům, protože platí vztah: 25 textových řádků × 14 skenovacích/obrazových řádků na výšku znaku=350 skenovacích řádků celkem. V grafickém režimu je zvolena hodnota 348 skenovacích řádků především z toho důvodu, že je toto číslo dělitelné čtyřmi, což souvisí s režimem přístupu do obrazové paměti, jehož princip bude popsán v následujícím textu (ostatně změnou řídicích registrů čipu MC6845 lze počet obrazových řádků v určitém rozsahu měnit, takže lze dosáhnout i 350 řádků – pokud vůbec někdo pozná vizuální rozdíl).

Obrázek 11: Hra Simcity v režimu grafické karty Hercules. Z předchozího odstavce je patrné, že konkrétní barvové schéma se liší podle typu monitoru (a mnohé monitory navíc měly tlačítko pro inverzní zobrazení).

12. Postup pro přepnutí do grafického režimu

V případě, že budeme chtít přepnout kartu Hercules do grafického režimu, nemůžeme použít BIOS, protože tato karta není BIOSem podporována. Zbývá nám tedy oblíbený nízkoúrovňový přístup, konkrétně provedení následujících čtyř kroků:

  1. Povolíme změnu z textového režimu na režim grafický (I/O port 0×3bf)
  2. Přepneme se do grafického režimu a vypneme zobrazování (I/O port 0×3b8)
  3. Přeprogramujeme prvních dvanáct řídicích CRTC registrů
  4. Povolíme zobrazování (I/O port 0×3b8)

Pro změnu portů 0×3bf a 0×3b8 použijeme pomocná makra nazvaná set_config a set_control:

; nastaveni konfiguracniho registru
%macro set_config 1
        mov dx, hercules_config
        mov al, %1    ; ridici registr
        out dx, al
%endmacro
 
; nastaveni ridiciho registru
%macro set_control 1
        mov dx, hercules_control
        mov al, %1    ; ridici registr
        out dx, al
%endmacro

Jak však nastavit CRTC registry? Tato informace je téměř ztracena v temných zákoutích internetu (ostatně se jedná o informace z roku 1983), takže si uveďme korektní a podporované hodnoty CRTC registrů (resp. prvních dvanácti registrů, další nemají z hlediska zobrazování grafiky význam). Povšimněte si, že i pro grafický režim pracujeme s jednotkou „znak“ a nikoli „pixel“:

Číslo registru Hodnota (dec) Hodnota (hex) Význam
0 53 35 celkový počet znaků horizontálně – 1, včetně okrajů (tedy nezobrazených znaků)
1 45 2d počet horizontálně zobrazených znaků
2 46 2e horizontální pozice synchronizačního signálu
3 7 07 šířka horizontálního synchronizačního signálu
     
4 91 5b celkový počet textových řádků (včetně okrajů)
5 2 02 mikroposun textových řádků po jednotlivých obrazových řádcích
6 87 57 zobrazený počet textových řádků (87*4=348 obrazových řádků celkem)
7 87 57 vertikální pozice synchronizačního signálu
     
8 2 2 režim prokládání (interlace) a posunutí
     
9 3 3 počet obrazových řádků pro jeden textový řádek – 1 – výška znaku (tedy 4 mikrořádky)
     
10 0 0 začátek hardwarového kurzoru
11 0 0 konec hardwarového kurzoru
     
12 0 0 počáteční adresa obrazové paměti (vyšší bajt)
13 0 0 počáteční adresa obrazové paměti (nižší bajt)
14 0 0 adresa kurzoru – vyšší bajt
15 0 0 adresa kurzoru – nižší bajt
16 0 0 adresa světelného pera – vyšší bajt
17 0 0 adresa světelného pera – nižší bajt

Prvních dvanáct hodnot si uložíme přímo do našeho programu:

gtable: db      35h,2dh,2eh,07h
        db      5bh,02h,57h,57h
        db      02h,03h,00h,00h

Jen pro připomenutí, jaký význam mají čítače a hodnoty komparátorů v prvních čtyřech registrech:

          1         2         3         4         5
 12345678901234567890123456789012345678901234567890123456  ← čítač znaků
|                                            ||      ||
|     běžný viditelný textový řádek          || sync ||
|                                            ||      ||
                                             ↑↑      ↑↑
                                            R1 R2   R2+R3=R0
Poznámka: jeden „znak“ v této chvíli odpovídá šestnácti horizontálním pixelům, takže hodnota 45 znamená 45×16=720 pixelů.

Celý podprogram pro nastavení grafického režimu:

init_graphics:
        set_config enable
        set_control graphics
 
        ; inicializace ridicich registru cipu Motorola 6845
        mov     si, gtable               ; DS:SI obsahuje adresu tabulky s hodnotami registru
 
        mov     cx, 12                   ; pocet nastavovanych parametru
        xor     ah, ah                   ; zaciname registrem cislo 0
 
parms:
        mov     dx, hercules_index       ; port pro zapis
        mov     al, ah
        out     dx, al                   ; zapis cisla registru na port
 
        mov     dx, hercules_data        ; port pro zapis
        lodsb                            ; precist hodnotu registru z tabulky
        out     dx, al                   ; zapis hodnoty registru na port
 
        inc     ah                       ; dalsi CRTC registr
        loop    parms                    ; dalsi iterace
 
        set_control graphics + screen_on ; zapnuti obrazovky
        ret                              ; vse hotovoa

Podívejme se na výsledek:

Obrázek 12: Byla vyplněna přesně jedna čtvrtina obrazovky – každý čtvrtý řádek (nyní již tedy známe strukturu video RAM).

13. Úplný zdrojový kód dnešního čtvrtého demonstračního příkladu

Úplný zdrojový kód demonstračního příkladu, který provede naprogramování karty Hercules tak, aby se použil grafický režim, vypadá následovně:

; Graficky rezim karty Hercules s rozlisenim 720x348 znaku.
;
; preklad pomoci:
;     nasm -f bin -o hercules.com hercules_gfx_mode_1.asm
;
; nebo pouze:
;     nasm -o hercules.com hercules_gfx_mode_1.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty Hercules
hercules_index    equ 0x3b4
hercules_data     equ 0x3b5
hercules_control  equ 0x3b8
hercules_status   equ 0x3ba
hercules_config   equ 0x3bf
 
; ridici bity
screen_on equ 0x08
graphics  equ 0x02
text      equ 0x20
enable    equ 0x03
 
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni konfiguracniho registru
%macro set_config 1
        mov dx, hercules_config
        mov al, %1    ; ridici registr
        out dx, al
%endmacro
 
; nastaveni ridiciho registru
%macro set_control 1
        mov dx, hercules_control
        mov al, %1    ; ridici registr
        out dx, al
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        call init_graphics
 
        mov ax, 0xb000
        mov es, ax
        mov di, 0         ; nyni ES:DI obsahuje adresu prvniho znaku ve video RAM
 
        mov cx, 90*348/4  ; pocet zapisovanych bajtu
        mov al, 255       ; kod zapisovaneho bajtu
opak:
        stosb             ; zapis bajtu
        loop opak         ; opakujeme CX-krat
 
        wait_key
        exit              ; hotovo
 
 
init_graphics:
        set_config enable
        set_control graphics
 
        ; inicializace ridicich registru cipu Motorola 6845
        mov     si, gtable               ; DS:SI obsahuje adresu tabulky s hodnotami registru
 
        mov     cx, 12                   ; pocet nastavovanych parametru
        xor     ah, ah                   ; zaciname registrem cislo 0
 
parms:
        mov     dx, hercules_index       ; port pro zapis
        mov     al, ah
        out     dx, al                   ; zapis cisla registru na port
 
        mov     dx, hercules_data        ; port pro zapis
        lodsb                            ; precist hodnotu registru z tabulky
        out     dx, al                   ; zapis hodnoty registru na port
 
        inc     ah                       ; dalsi CRTC registr
        loop    parms                    ; dalsi iterace
 
        set_control graphics + screen_on ; zapnuti obrazovky
        ret                              ; vse hotovoa
 
 
gtable: db      35h,2dh,2eh,07h
        db      5bh,02h,57h,57h
        db      02h,03h,00h,00h

14. Vylepšení kódu: efektivnější zápis do registrů CRTC

Zápis do některého řídicího registru CRTC byl v předchozím demonstračním příkladu vyřešen tak, že se nejdříve zapsalo číslo registru na port 3b4 a následně se zapsala hodnota registru na port 3b5:

        mov     dx, hercules_index       ; port pro zapis
        mov     al, ah
        out     dx, al                   ; zapis cisla registru na port
 
        mov     dx, hercules_data        ; port pro zapis
        lodsb                            ; precist hodnotu registru z tabulky
        out     dx, al                   ; zapis hodnoty registru na port

Jedná se sice o zcela korektní postup, ale můžeme postupovat i odlišným způsobem pokud si uvědomíme, že porty 3b4 a 3b5 leží za sebou. Číslo portu je uloženo v registru DX, takže pouze operacemi inc a dec dosáhneme stejného výsledku, ovšem rychleji a taktéž kratším kódem:

        mov     al, ah                   ; zapis cisla registru
        out     dx, al
 
        inc     dx                       ; adresa portu datoveho registru
        lodsb                            ; precist hodnotu registru z tabulky
        out     dx, al                   ; zapis hodnoty registru na port
        dec     dx                       ; obnoveni cisla portu

Instrukce inc a dec jsou každá o dva bajty kratší a taktéž každá o jeden takt rychlejší. Nejedná se tedy o nijak raketové urychlení ani zkrácení, ale programátor alespoň ukázal profesionální znalost „strojáku“.

Výsledek bude totožný, jako tomu bylo v předchozím příkladu:

Obrázek 13: Obrazovka má naprosto stejný obsah, jako tomu bylo na obrázku 11.

15. Úplný zdrojový kód dnešního pátého demonstračního příkladu

Opět se podívejme na úplný zdrojový kód dnes již pátého demonstračního příkladu:

; Graficky rezim karty Hercules s rozlisenim 720x348 znaku.
;
; preklad pomoci:
;     nasm -f bin -o hercules.com hercules_gfx_mode_2.asm
;
; nebo pouze:
;     nasm -o hercules.com hercules_gfx_mode_2.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty Hercules
hercules_index    equ 0x3b4
hercules_data     equ 0x3b5
hercules_control  equ 0x3b8
hercules_status   equ 0x3ba
hercules_config   equ 0x3bf
 
; ridici bity
screen_on equ 0x08
graphics  equ 0x02
text      equ 0x20
enable    equ 0x03
 
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni konfiguracniho registru
%macro set_config 1
        mov dx, hercules_config
        mov al, %1    ; ridici registr
        out dx, al
%endmacro
 
; nastaveni ridiciho registru
%macro set_control 1
        mov dx, hercules_control
        mov al, %1    ; ridici registr
        out dx, al
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        call init_graphics
 
        mov ax, 0xb000
        mov es, ax
        mov di, 0         ; nyni ES:DI obsahuje adresu prvniho znaku ve video RAM
 
        mov cx, 90*348/4  ; pocet zapisovanych bajtu
        mov al, 255       ; kod zapisovaneho bajtu
opak:
        stosb             ; zapis bajtu
        loop opak         ; opakujeme CX-krat
 
        wait_key
        exit              ; hotovo
 
 
init_graphics:
        set_config enable
        set_control graphics
 
        ; inicializace ridicich registru cipu Motorola 6845
        mov     si, gtable               ; DS:SI obsahuje adresu tabulky s hodnotami registru
 
        mov     dx, hercules_index       ; registr pro zapis
        mov     cx, 12                   ; pocet nastavovanych parametru
        xor     ah, ah                   ; zaciname registrem cislo 0
 
parms:  mov     al, ah                   ; zapis cisla registru
        out     dx, al
 
        inc     dx                       ; adresa portu datoveho registru
        lodsb                            ; precist hodnotu registru z tabulky
        out     dx, al                   ; zapis hodnoty registru na port
 
        inc     ah                       ; dalsi CRTC registr
        dec     dx                       ; obnoveni cisla portu
        loop    parms                    ; dalsi iterace
 
        set_control graphics + screen_on ; zapnuti obrazovky
        ret                              ; vse hotovo
 
 
gtable: db      35h,2dh,2eh,07h
        db      5bh,02h,57h,57h
        db      02h,03h,00h,00h

16. Postup při vykreslení jednoho pixelu v grafickém režimu karty Hercules

Jak se v grafickém režimu karty Hercules vykreslí jeden pixel? Můžeme postupovat podobně, jako v režimu 640×200 karty CGA, ovšem tyto režimy se od sebe odlišují, a to hned ve třech oblastech:

  1. Horizontální rozlišení je rovno 720 pixelů, což není tak „kulaté“ číslo, jako 640 (při násobení je to jedno, při bitových posunech je to horší).
  2. Vertikální rozlišení je rovno 348 pixelům, takže případné násobení y-ové souřadnice již musíme provádět se šestnáctibitovými vstupy.
  3. Obraz je rozdělen nejenom na sudé a liché řádky, ale na řádky dělitelné 4, řádky, kde po dělení 4 získáme 1, 2, popř. 3. Celý výpočet adresy pixelu je tedy nepatrně komplikovanější.

Adresa pro operaci zápisu či čtení pixelu zadaného souřadnicemi x, y se vypočte následovně:

offset = 0x2000 * (y % 4) + 90 * (y >> 2) + (x >> 3)

Index bitu, který se má zapsat či přečíst na výše vypočtené adrese, lze vyjádřit takto:

offset bit = 7 - (x % 8)

I přes určitou komplikovanost je tedy možné se nechat inspirovat kartou CGA:

; Vykresleni pixelu
; AX - x-ova souradnice
; BX - y-ova souradnice (staci len BL)
putpixel:
        mov dx, 0xb800     ; zacatek prvni stranky Video RAM
        test bx, 1         ; test, zda se jedna o sudy nebo lichy radek na obrazovce
        jz odd_line
        add dx, 8192/16
odd_line:
        mov es, dx         ; nyni obsahuje ES bud prvni stranku Video RAM nebo stranku druhou
 
        mov cl, al
        and cl, 7          ; pouze spodni 3 bity x-ove souradnice
 
        shr ax, 1
        shr ax, 1
        shr ax, 1          ; x/8
        mov di, ax         ; horizontalni posun pocitany v bajtech
 
        mov ax, bx         ; y-ova souradnice
        and al, 0xfe       ; nejnizsi bit urcuje lichy/sudy radek -> nyni ignorovat
        shl ax, 1          ; y*4
        shl ax, 1          ; y*8
        shl ax, 1          ; y*16
        add di, ax         ; pricist cast y-oveho posunu
        shl ax, 1          ; y*32
        shl ax, 1          ; y*64
        add di, ax         ; pricist zbytek y-oveho posunu
                           ; -> y*16 + y*64 = y*80
 
        mov al, 0x80       ; vypocitat masku pixelu
        shr al, cl
        or [es:di], al     ; vlastni vykresleni pixelu
 
        ret

17. Předpočet adres jednotlivých obrazových řádků

Můžeme ovšem postupovat i odlišným způsobem, konkrétně tak, že si adresy začátků jednotlivých obrazových řádků necháme předpočítat do tabulky s 384 šestnáctibitovými hodnotami (offsety). Tyto offsety mohou vypadat následovně (jedná se jen o začátek tabulky):

                ;offsets into HGC regen buffer for each scan line
HGCRegen        dw      0,8192,16384,24576,90,8282,16474,24666
                dw      180,8372,16564,24756,270,8462,16654,24846
                dw      360,8552,16744,24936,450,8642,16834,25026
                dw      540,8732,16924,25116,630,8822,17014,25206
                dw      720,8912,17104,25296,810,9002,17194,25386
                dw      900,9092,17284,25476,990,9182,17374,25566
                dw      1080,9272,17464,25656,1170,9362,17554,25746

Povšimněte si, že první řádek má offset roven 0, druhý řádek 8192 (druhá čtvrtina obrazové paměti) atd. Až pátý řádek má offset 90 (odpovídá 720 pixelům) atd. atd.

Výsledný binární soubor se nám sice zvětší, zde konkrétně na 841 bajtů, ovšem samotný výpočet adresy pixelu se zjednoduší a zrychlí:

; vykresleni pixelu
; kod prevzaty z Fractintu a upraveny do podoby kompatibilni s NASMem
; provedeny dalsi optimalizace pro Intel 8086
putpixel:
        mov     si, bx           ; y-ova souradnice
        shl     si, 1            ; vypositat offset (v tabulce jsou ulozena slova, ne bajty)
        lea     bx, HGCRegen     ; adresa tabulky
        mov     si, [bx+si]      ; ziskat adresu obrazoveho radku odpovidajiciho y-ove souradnici

Následuje výpočet adresy v rámci jednoho řádku, což se obejde bez násobení:

        mov     cx, ax           ; uschovat x-ovou souradnici (registr AX se prepise)
        shr     ax, 1
        shr     ax, 1
        shr     ax, 1            ; vydelit osmi -> ziskani offsetu v ramci obrazoveho radku
 
        add     si, ax           ; nyni je v ES:SI adresa zapisovaneho bajtu

A následuje klasika, kterou již známe – výpočet masky. Zde navíc máme doplněn kód pro vykreslení černého pixelu (negativní maska):

        and     cx, 0x07         ; bit v ramci bajtu
        mov     al, 0x80         ; vypocet bitove masky
        shr     al, cl           ; bitova maska je nyni v AL
 
        mov     cx, 0xb000       ; segment video RAM
mov es, cx ; do registru ES

cmp dl, 0 ; ma se vykreslit cerny pixel? je black_pixel ; pokud ano -> skok   white_pixel: or es:[si], al ; vykresleni bileho pixelu ret ; konec black_pixel: xor al, 0xff ; inverze masky and es:[si], al ; vykresleni cerneho pixelu ret ; konec
Poznámka: jak je napsáno v komentáři, původně byl tento kód použit ve Fractintu, ale provedl jsem určité optimalizace – což je po těch letech poněkud zvláštní (čekal bych, že kód bude dokonalý, ale vypadalo to, že je částečně vygenerován překladačem a bylo ho možné zkrátit a urychlit).

18. Úplný zdrojový kód dnešního šestého demonstračního příkladu

Pokud budeme výše popsanou subrutinu putpixel postupně volat se zvyšujícími se souřadnicemi [x, y], vykreslí se diagonální úsečka:

Obrázek 14: Vykreslení úsečky složené z jednotlivých pixelů.

ict ve školství 24

A takto vypadá úplný text dnešního posledního demonstračního příkladu pro vykreslení pixelů v grafickém režimu karty Hercules:

; Graficky rezim karty Hercules s rozlisenim 720x348 znaku.
;
; preklad pomoci:
;     nasm -f bin -o hercules.com hercules_gfx_mode_2.asm
;
; nebo pouze:
;     nasm -o hercules.com hercules_gfx_mode_2.asm
 
 
;-----------------------------------------------------------------------------
 
; registry karty Hercules
hercules_index    equ 0x3b4
hercules_data     equ 0x3b5
hercules_control  equ 0x3b8
hercules_status   equ 0x3ba
hercules_config   equ 0x3bf
 
; ridici bity
screen_on equ 0x08
graphics  equ 0x02
text      equ 0x20
enable    equ 0x03
 
 
 
; ukonceni procesu a navrat do DOSu
%macro exit 0
        mov     ah, 0x4c
        int     0x21
%endmacro
 
; vyprazdneni bufferu klavesnice a cekani na klavesu
%macro wait_key 0
        xor     ax, ax
        int     0x16
%endmacro
 
; nastaveni konfiguracniho registru
%macro set_config 1
        mov dx, hercules_config
        mov al, %1    ; ridici registr
        out dx, al
%endmacro
 
; nastaveni ridiciho registru
%macro set_control 1
        mov dx, hercules_control
        mov al, %1    ; ridici registr
        out dx, al
%endmacro
 
;-----------------------------------------------------------------------------
org  0x100        ; zacatek kodu pro programy typu COM (vzdy se zacina na 256)
 
start:
        call init_graphics
 
        mov ax, 0xb000
        mov es, ax
        mov di, 0         ; nyni ES:DI obsahuje adresu prvniho znaku ve video RAM
 
        mov cx, 90*348    ; pocet zapisovanych bajtu
        xor al, al        ; kod zapisovaneho bajtu
        rep stosb         ; vymazat obrazovku
 
        xor ax, ax        ; x-ova souradnice
        mov cx, 348       ; pocitadlo vykreslenych pixelu
opak:
        mov  bx, ax       ; y-ova souradnice
        mov  dl, 1        ; barva vykreslovaneho pixelu
 
        push ax           ; uchovat (tyto registry se v subrutine poskodi)
        push cx           ; uchovat (tyto registry se v subrutine poskodi)
        call putpixel     ; ax=x, bx=y, dl=barva
        pop cx            ; obnovit
        pop ax            ; obnovit
 
        inc ax            ; x+=1
        loop opak         ; a dalsi pixel
 
        wait_key
        exit              ; hotovo
 
 
init_graphics:
        set_config enable
        set_control graphics
 
        ; inicializace ridicich registru cipu Motorola 6845
        mov     si, gtable               ; DS:SI obsahuje adresu tabulky s hodnotami registru
 
        mov     dx, hercules_index       ; registr pro zapis
        mov     cx, 12                   ; pocet nastavovanych parametru
        xor     ah, ah                   ; zaciname registrem cislo 0
 
parms:  mov     al, ah                   ; zapis cisla registru
        out     dx, al
 
        inc     dx                       ; adresa portu datoveho registru
        lodsb                            ; precist hodnotu registru z tabulky
        out     dx, al                   ; zapis hodnoty registru na port
 
        inc     ah                       ; dalsi CRTC registr
        dec     dx                       ; obnoveni cisla portu
        loop    parms                    ; go do another one
 
        set_control graphics + screen_on ; zapnuti obrazovky
        ret                              ; vse hotovoa
 
 
gtable: db      35h,2dh,2eh,07h
        db      5bh,02h,57h,57h
        db      02h,03h,00h,00h
 
 
; vykresleni pixelu
; kod prevzaty z Fractintu a upraveny do podoby kompatibilni s NASMem
; provedeny dalsi optimalizace pro Intel 8086
putpixel:
        mov     si, bx           ; y-ova souradnice
        shl     si, 1            ; vypositat offset (v tabulce jsou ulozena slova, ne bajty)
        lea     bx, HGCRegen     ; adresa tabulky
        mov     si, [bx+si]      ; ziskat adresu obrazoveho radku odpovidajiciho y-ove souradnici
 
        mov     cx, ax           ; uschovat x-ovou souradnici (registr AX se prepise)
        shr     ax, 1
        shr     ax, 1
        shr     ax, 1            ; vydelit osmi -> ziskani offsetu v ramci obrazoveho radku
 
        add     si, ax           ; nyni je v ES:SI adresa zapisovaneho bajtu
 
        and     cx, 0x07         ; bit v ramci bajtu
        mov     al, 0x80         ; vypocet bitove masky
        shr     al, cl           ; bitova maska je nyni v AL

mov cx, 0xb000 ; segment video RAM
mov es, cx ; do registru ES
cmp dl, 0 ; ma se vykreslit cerny pixel? je black_pixel ; pokud ano -> skok   white_pixel: or es:[si], al ; vykresleni bileho pixelu ret ; konec black_pixel: xor al, 0xff ; inverze masky and es:[si], al ; vykresleni cerneho pixelu ret ; konec     ;offsets into HGC regen buffer for each scan line HGCRegen dw 0,8192,16384,24576,90,8282,16474,24666 dw 180,8372,16564,24756,270,8462,16654,24846 dw 360,8552,16744,24936,450,8642,16834,25026 dw 540,8732,16924,25116,630,8822,17014,25206 dw 720,8912,17104,25296,810,9002,17194,25386 dw 900,9092,17284,25476,990,9182,17374,25566 dw 1080,9272,17464,25656,1170,9362,17554,25746 dw 1260,9452,17644,25836,1350,9542,17734,25926 dw 1440,9632,17824,26016,1530,9722,17914,26106 dw 1620,9812,18004,26196,1710,9902,18094,26286 dw 1800,9992,18184,26376,1890,10082,18274,26466 dw 1980,10172,18364,26556,2070,10262,18454,26646 dw 2160,10352,18544,26736,2250,10442,18634,26826 dw 2340,10532,18724,26916,2430,10622,18814,27006 dw 2520,10712,18904,27096,2610,10802,18994,27186 dw 2700,10892,19084,27276,2790,10982,19174,27366 dw 2880,11072,19264,27456,2970,11162,19354,27546 dw 3060,11252,19444,27636,3150,11342,19534,27726 dw 3240,11432,19624,27816,3330,11522,19714,27906 dw 3420,11612,19804,27996,3510,11702,19894,28086 dw 3600,11792,19984,28176,3690,11882,20074,28266 dw 3780,11972,20164,28356,3870,12062,20254,28446 dw 3960,12152,20344,28536,4050,12242,20434,28626 dw 4140,12332,20524,28716,4230,12422,20614,28806 dw 4320,12512,20704,28896,4410,12602,20794,28986 dw 4500,12692,20884,29076,4590,12782,20974,29166 dw 4680,12872,21064,29256,4770,12962,21154,29346 dw 4860,13052,21244,29436,4950,13142,21334,29526 dw 5040,13232,21424,29616,5130,13322,21514,29706 dw 5220,13412,21604,29796,5310,13502,21694,29886 dw 5400,13592,21784,29976,5490,13682,21874,30066 dw 5580,13772,21964,30156,5670,13862,22054,30246 dw 5760,13952,22144,30336,5850,14042,22234,30426 dw 5940,14132,22324,30516,6030,14222,22414,30606 dw 6120,14312,22504,30696,6210,14402,22594,30786 dw 6300,14492,22684,30876,6390,14582,22774,30966 dw 6480,14672,22864,31056,6570,14762,22954,31146 dw 6660,14852,23044,31236,6750,14942,23134,31326 dw 6840,15032,23224,31416,6930,15122,23314,31506 dw 7020,15212,23404,31596,7110,15302,23494,31686 dw 7200,15392,23584,31776,7290,15482,23674,31866 dw 7380,15572,23764,31956,7470,15662,23854,32046 dw 7560,15752,23944,32136,7650,15842,24034,32226 dw 7740,15932,24124,32316

19. Repositář s demonstračními příklady

Demonstrační příklady napsané v assembleru, které jsou určené pro překlad pomocí assembleru NASM, byly uložen do Git repositáře, který je dostupný na adrese https://github.com/tisnik/8bit-fame. Jednotlivé demonstrační příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý (dnes již poměrně rozsáhlý) repositář:

# Příklad Stručný popis Adresa
1 hello.asm program typu „Hello world“ naprogramovaný v assembleru pro systém DOS https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello.asm
2 hello_shorter.asm kratší varianta výskoku z procesu zpět do DOSu https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_shorter.asm
3 hello_wait.asm čekání na stisk klávesy https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_wait.asm
4 hello_macros.asm realizace jednotlivých částí programu makrem https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hello_macros.asm
       
5 gfx4_putpixel.asm vykreslení pixelu v grafickém režimu 4 https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_putpixel.asm
6 gfx6_putpixel.asm vykreslení pixelu v grafickém režimu 6 https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel.asm
7 gfx4_line.asm vykreslení úsečky v grafickém režimu 4 https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_line.asm
8 gfx6_line.asm vykreslení úsečky v grafickém režimu 6 https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_line.asm
       
9 gfx6_fill1.asm vyplnění obrazovky v grafickém režimu, základní varianta https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill1.asm
10 gfx6_fill2.asm vyplnění obrazovky v grafickém režimu, varianta s instrukcí LOOP https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill2.asm
11 gfx6_fill3.asm vyplnění obrazovky instrukcí REP STOSB https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill3.asm
12 gfx6_fill4.asm vyplnění obrazovky, synchronizace vykreslování s paprskem https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_fill4.asm
       
13 gfx4_image1.asm vykreslení rastrového obrázku získaného z binárních dat, základní varianta https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image1.asm
14 gfx4_image2.asm varianta vykreslení rastrového obrázku s využitím instrukce REP MOVSB https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image2.asm
15 gfx4_image3.asm varianta vykreslení rastrového obrázku s využitím instrukce REP MOVSW https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image3.asm
16 gfx4_image4.asm korektní vykreslení všech sudých řádků bitmapy https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image4.asm
17 gfx4_image5.asm korektní vykreslení všech sudých i lichých řádků bitmapy https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image5.asm
       
18 gfx4_image6.asm nastavení barvové palety před vykreslením obrázku https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image6.asm
19 gfx4_image7.asm nastavení barvové palety před vykreslením obrázku, snížená intenzita barev https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image7.asm
20 gfx4_image8.asm postupná změna barvy pozadí https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx4_image8.asm
       
21 gfx6_putpixel1.asm vykreslení pixelu, základní varianta se 16bitovým násobením https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel1.asm
22 gfx6_putpixel2.asm vykreslení pixelu, varianta s osmibitovým násobením https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel2.asm
23 gfx6_putpixel3.asm vykreslení pixelu, varianta bez násobení https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel3.asm
24 gfx6_putpixel4.asm vykreslení pixelu přes obrázek, nekorektní chování (přepis obrázku) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel4.asm
25 gfx6_putpixel5.asm vykreslení pixelu přes obrázek, korektní varianta pro bílé pixely https://github.com/tisnik/8bit-fame/blob/master/pc-dos/gfx6_putpixel5.asm
       
26 cga_text_mode1.asm standardní textový režim s rozlišením 40×25 znaků https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode1.asm
27 cga_text_mode3.asm standardní textový režim s rozlišením 80×25 znaků https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode3.asm
28 cga_text_mode_intensity.asm změna významu nejvyššího bitu atributového bajtu: vyšší intenzita namísto blikání https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_intensity.asm
29 cga_text_mode_cursor.asm změna tvaru textového kurzoru https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_cursor.asm
30 cga_text_gfx1.asm zobrazení „rastrové mřížky“: pseudografický režim 160×25 pixelů (interně textový režim) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_gfx1.asm
31 cga_text_mode_char_height.asm změna výšky znaků https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_mode_char_height.asm
32 cga_text_160×100.asm grafický režim 160×100 se šestnácti barvami (interně upravený textový režim) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/cga_text_160×100.asm
       
33 hercules_text_mode1.asm využití standardního textového režimu společně s kartou Hercules https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_text_mode1.asm
34 hercules_text_mode2.asm zákaz blikání v textových režimech https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_text_mode2.asm
35 hercules_turn_off.asm vypnutí generování video signálu https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_turn_off.asm
36 hercules_gfx_mode1.asm přepnutí karty Hercules do grafického režimu (základní varianta) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_gfx_mode1.asm
37 hercules_gfx_mode2.asm přepnutí karty Hercules do grafického režimu (vylepšená varianta) https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_gfx_mode2.asm
38 hercules_putpixel.asm subrutina pro vykreslení jediného pixelu na kartě Hercules https://github.com/tisnik/8bit-fame/blob/master/pc-dos/hercules_putpixel.asm

20. Odkazy na Internetu

  1. The Intel 8088 Architecture and Instruction Set
    https://people.ece.ubc.ca/~ed­c/464/lectures/lec4.pdf
  2. x86 Opcode Structure and Instruction Overview
    https://pnx.tf/files/x86_op­code_structure_and_instruc­tion_overview.pdf
  3. x86 instruction listings (Wikipedia)
    https://en.wikipedia.org/wi­ki/X86_instruction_listin­gs
  4. x86 assembly language (Wikipedia)
    https://en.wikipedia.org/wi­ki/X86_assembly_language
  5. Intel Assembler (Cheat sheet)
    http://www.jegerlehner.ch/in­tel/IntelCodeTable.pdf
  6. 25 Microchips That Shook the World
    https://spectrum.ieee.org/tech-history/silicon-revolution/25-microchips-that-shook-the-world
  7. Chip Hall of Fame: MOS Technology 6502 Microprocessor
    https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-mos-technology-6502-microprocessor
  8. Chip Hall of Fame: Intel 8088 Microprocessor
    https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-intel-8088-microprocessor
  9. Jak se zrodil procesor?
    https://www.root.cz/clanky/jak-se-zrodil-procesor/
  10. Apple II History Home
    http://apple2history.org/
  11. The 8086/8088 Primer
    https://www.stevemorse.or­g/8086/index.html
  12. flat assembler: Assembly language resources
    https://flatassembler.net/
  13. FASM na Wikipedii
    https://en.wikipedia.org/wiki/FASM
  14. Fresh IDE FASM inside
    https://fresh.flatassembler.net/
  15. MS-DOS Version 4.0 Programmer's Reference
    https://www.pcjs.org/docu­ments/books/mspl13/msdos/dos­ref40/
  16. INT 21 – DOS Function Dispatcher (DOS)
    https://www.stanislavs.or­g/helppc/int21.html
  17. DOS API (Wikipedia)
    https://en.wikipedia.org/wiki/DOS_API
  18. Bit banging
    https://en.wikipedia.org/wi­ki/Bit_banging
  19. IBM Basic assembly language and successors (Wikipedia)
    https://en.wikipedia.org/wi­ki/IBM_Basic_assembly_lan­guage_and_successors
  20. X86 Assembly/Bootloaders
    https://en.wikibooks.org/wi­ki/X86_Assembly/Bootloaders
  21. Počátky grafiky na PC: grafické karty CGA a Hercules
    https://www.root.cz/clanky/pocatky-grafiky-na-pc-graficke-karty-cga-a-hercules/
  22. Co mají společného Commodore PET/4000, BBC Micro, Amstrad CPC i grafické karty MDA, CGA a Hercules?
    https://www.root.cz/clanky/co-maji-spolecneho-commodore-pet-4000-bbc-micro-amstrad-cpc-i-graficke-karty-mda-cga-a-hercules/
  23. Karta EGA: první použitelná barevná grafika na PC
    https://www.root.cz/clanky/karta-ega-prvni-pouzitelna-barevna-grafika-na-pc/
  24. RGB Classic Games
    https://www.classicdosgames.com/
  25. Turbo Assembler (Wikipedia)
    https://en.wikipedia.org/wi­ki/Turbo_Assembler
  26. Microsoft Macro Assembler
    https://en.wikipedia.org/wi­ki/Microsoft_Macro_Assembler
  27. IBM Personal Computer (Wikipedia)
    https://en.wikipedia.org/wi­ki/IBM_Personal_Computer
  28. Intel 8251
    https://en.wikipedia.org/wi­ki/Intel_8251
  29. Intel 8253
    https://en.wikipedia.org/wi­ki/Intel_8253
  30. Intel 8255
    https://en.wikipedia.org/wi­ki/Intel_8255
  31. Intel 8257
    https://en.wikipedia.org/wi­ki/Intel_8257
  32. Intel 8259
    https://en.wikipedia.org/wi­ki/Intel_8259
  33. Support/peripheral/other chips – 6800 family
    http://www.cpu-world.com/Support/6800.html
  34. Motorola 6845
    http://en.wikipedia.org/wi­ki/Motorola_6845
  35. The 6845 Cathode Ray Tube Controller (CRTC)
    http://www.tinyvga.com/6845
  36. CRTC operation
    http://www.6502.org/users/an­dre/hwinfo/crtc/crtc.html
  37. 6845 – Motorola CRT Controller
    https://stanislavs.org/hel­ppc/6845.html
  38. The 6845 Cathode Ray Tube Controller (CRTC)
    http://www.tinyvga.com/6845
  39. Motorola 6845 and bitwise graphics
    https://retrocomputing.stac­kexchange.com/questions/10996/mo­torola-6845-and-bitwise-graphics
  40. IBM Monochrome Display Adapter
    http://en.wikipedia.org/wi­ki/Monochrome_Display_Adap­ter
  41. Color Graphics Adapter
    http://en.wikipedia.org/wi­ki/Color_Graphics_Adapter
  42. Color Graphics Adapter and the Brown color in IBM 5153 Color Display
    https://www.aceinnova.com/en/e­lectronics/cga-and-the-brown-color-in-ibm-5153-color-display/
  43. The Modern Retrocomputer: An Arduino Driven 6845 CRT Controller
    https://hackaday.com/2017/05/14/the-modern-retrocomputer-an-arduino-driven-6845-crt-controller/
  44. flat assembler: Assembly language resources
    https://flatassembler.net/
  45. FASM na Wikipedii
    https://en.wikipedia.org/wiki/FASM
  46. Fresh IDE FASM inside
    https://fresh.flatassembler.net/
  47. MS-DOS Version 4.0 Programmer's Reference
    https://www.pcjs.org/docu­ments/books/mspl13/msdos/dos­ref40/
  48. INT 21 – DOS Function Dispatcher (DOS)
    https://www.stanislavs.or­g/helppc/int21.html
  49. DOS API (Wikipedia)
    https://en.wikipedia.org/wiki/DOS_API
  50. IBM Basic assembly language and successors (Wikipedia)
    https://en.wikipedia.org/wi­ki/IBM_Basic_assembly_lan­guage_and_successors
  51. X86 Assembly/Arithmetic
    https://en.wikibooks.org/wi­ki/X86_Assembly/Arithmetic
  52. Art of Assembly – Arithmetic Instructions
    http://oopweb.com/Assembly/Do­cuments/ArtOfAssembly/Volu­me/Chapter6/CH06–2.html
  53. ASM Flags
    http://www.cavestory.org/gu­ides/csasm/guide/asm_flag­s.html
  54. Status Register
    https://en.wikipedia.org/wi­ki/Status_register
  55. Linux assemblers: A comparison of GAS and NASM
    http://www.ibm.com/develo­perworks/library/l-gas-nasm/index.html
  56. Programovani v assembleru na OS Linux
    http://www.cs.vsb.cz/gryga­rek/asm/asmlinux.html
  57. Is it worthwhile to learn x86 assembly language today?
    https://www.quora.com/Is-it-worthwhile-to-learn-x86-assembly-language-today?share=1
  58. Why Learn Assembly Language?
    http://www.codeproject.com/Ar­ticles/89460/Why-Learn-Assembly-Language
  59. Is Assembly still relevant?
    http://programmers.stackex­change.com/questions/95836/is-assembly-still-relevant
  60. Why Learning Assembly Language Is Still a Good Idea
    http://www.onlamp.com/pub/a/on­lamp/2004/05/06/writegreat­code.html
  61. Assembly language today
    http://beust.com/weblog/2004/06/23/as­sembly-language-today/
  62. Assembler: Význam assembleru dnes
    http://www.builder.cz/rubri­ky/assembler/vyznam-assembleru-dnes-155960cz
  63. Programming from the Ground Up Book – Summary
    http://savannah.nongnu.or­g/projects/pgubook/
  64. DOSBox
    https://www.dosbox.com/
  65. The C Programming Language
    https://en.wikipedia.org/wi­ki/The_C_Programming_Langu­age
  66. Hercules Graphics Card (HCG)
    https://en.wikipedia.org/wi­ki/Hercules_Graphics_Card
  67. Complete 8086 instruction set
    https://content.ctcd.edu/cou­rses/cosc2325/m22/docs/emu8086in­s.pdf
  68. Complete 8086 instruction set
    https://yassinebridi.github.io/asm-docs/8086_instruction_set.html
  69. 8088 MPH by Hornet + CRTC + DESiRE (final version)
    https://www.youtube.com/wat­ch?v=hNRO7lno_DM
  70. Area 5150 by CRTC & Hornet (Party Version) / IBM PC+CGA Demo, Hardware Capture
    https://www.youtube.com/wat­ch?v=fWDxdoRTZPc
  71. 80×86 Integer Instruction Set Timings (8088 – Pentium)
    http://aturing.umcs.maine­.edu/~meadow/courses/cos335/80×86-Integer-Instruction-Set-Clocks.pdf
  72. Colour Graphics Adapter: Notes
    https://www.seasip.info/Vin­tagePC/cga.html
  73. Restoring A Vintage CGA Card With Homebrew HASL
    https://hackaday.com/2024/06/12/res­toring-a-vintage-cga-card-with-homebrew-hasl/
  74. Demoing An 8088
    https://hackaday.com/2015/04/10/de­moing-an-8088/
  75. Video Memory Layouts
    http://www.techhelpmanual.com/89-video_memory_layouts.html
  76. Screen Attributes
    http://www.techhelpmanual.com/87-screen_attributes.html
ikonka

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.