Obsah
1. Od reálného režimu k režimu chráněnému na procesorech 80286 a 80386
2. Šestnáctibitové adresy v reálném režimu
3. Šestnáctibitové adresy na čipech druhé a třetí generace 80×86
4. Rozepsání programové smyčky pro blokový přenos mezi dvěma segmenty
5. Offset přesahující hranici segmentu
6. Druhý příklad s offsetem, který přesahuje hranice segmentu
7. Chování mikroprocesoru Intel 80386 v reálném režimu
8. Skrytá část 80286: cache s deskriptory segmentů
9. Cache s deskriptory segmentů v reálném režimu
10. 32bitové adresy v reálném režimu
11. Deskriptory segmentů na čipech 80386
12. Ukázka adresace 32bitovými registry v reálném režimu
13. Rozepsání programové smyčky: přenos po 32bitech, offsety jsou realizovány 32bitovými registry
14. Přístup do obrazové paměti přes segment 0×0000 a 32bitový offset
15. Překročení limitu segmentu s využitím posunu adresy o konstantu
16. Naplnění cache s deskriptory přes „utajenou“ instrukci LOADALL
17. LOADALL na mikroprocesorech 80286
18. LOADALL na mikroprocesorech 80386
19. Repositář s demonstračními příklady
1. Od reálného režimu k režimu chráněnému na procesorech 80286 a 80386
V předchozím článku o nechvalně známém limitu 640kB RAM dostupné v operačním systému DOS jsme se zmínili o některých technikách, které vývojářům umožňovaly tuto bariéru překročit a využít tak celou dostupnou paměť počítače vybaveného mikroprocesory Intel 80286 a Intel 80386 [*]. Tyto techniky (kromě využití HMA, což nám však přidalo jen 65530 bajtů) nějakým způsobem musely pracovat s novým subsystémem mikroprocesorů – konkrétně se subsystémem určeným pro provozování mikroprocesorů v takzvaném chráněném režimu (protected mode). A – jako obvykle – se i v této oblasti nacházela spousta pastí, ať již způsobených snahou o zpětnou kompatibilitu, tak i „optimalizacemi“ a opomenutími na straně návrhu mikroprocesorů. Na druhou stranu však bylo možné využít různé triky a celý koncept chráněného režimu vhodným způsobem ohnout; tak, že se větší množství operační paměti dalo využít i v režimu reálném.
Ještě před tím, než si ukážeme možnosti chráněného režimu, je vhodné si zopakovat, jak se vlastně mikroprocesory chovaly v režimu reálném z pohledu adresování paměti. Protože i v běžném reálném režimu se dají využít některé vlastnosti režimu chráněného – jedná se o takzvané nereálné režimy (unreal mode), což ve skutečnosti nejsou nové režimy činnosti mikroprocesoru, ale ohnutí vlastností subsystému určeného pro chráněný režim.
2. Šestnáctibitové adresy v reálném režimu
Vraťme se na chvíli k prapůvodním čipům Intel 8086/8088. Připomeňme si, že tyto čipy měly vyvedených jen dvacet adresových vodičů a dokázaly tak adresovat přesně 1MB paměti. Výpočet adresy probíhal na základě kombinace segmentu a offsetu:
adresa = segment × 16 + offset
Jenže to není přesná (resp. ucelená) informace. Je nutno dodat, jakým způsobem byl vypočítán offset. Mikroprocesory Intel 8086/8088 totiž podporovaly tyto adresovací režimy:
Použitý zápis v assembleru | Adresovací režim |
---|---|
přímá adresa (16bit) | displacement/direct |
[BX] | register indirect |
[SI] | register indirect |
[DI] | register indirect |
[BX+SI] | based indexed mode |
[BX+DI] | based indexed mode |
[BP+SI] | based indexed mode |
[BP+DI] | based indexed mode |
[BP+offset8_bit] | based mode |
[BX+offset8_bit] | based mode |
[SI+offset8_bit] | indexed mode |
[DI+offset8_bit] | indexed mode |
[BP+offset16_bit] | based mode |
[BX+offset16_bit] | based mode |
[SI+offset16_bit] | indexed mode |
[DI+offset16_bit] | indexed mode |
[BX+SI+offset8_bit] | based indexed displacement |
[BX+DI+offset8_bit] | based indexed displacement |
[BP+SI+offset8_bit] | based indexed displacement |
[BP+DI+offset8_bit] | based indexed displacement |
[BX+SI+offset16_bit] | based indexed displacement |
[BX+DI+offset16_bit] | based indexed displacement |
[BP+SI+offset16_bit] | based indexed displacement |
[BP+DI+offset16_bit] | based indexed displacement |
Co to znamená v praxi? Řekněme, že v segmentovém registru DS bude uložena nula a v registru BX bude uložena hodnota 0×8000. Následně použijeme instrukci:
mov DS:[BX+0x8000], AL
Otázka zní, do jaké fyzické buňky RAM se uloží obsah registru AL? Máme dvě možnosti výpočtu. Triviální dosazení do vzorce pro výpočet adresy by vedlo k výpočtu:
0x0000 × 16 + 0x8000 + 0x8000 = 0x10000
Ovšem můžeme si také uvědomit, že sčítačka pro offsety je realizována v 16bitové ALU a tedy proběhne spíše něco takového:
0x0000 × 16 + (0x8000 + 0x8000) & 0xffff = 0x00000
Ve skutečnosti je správný druhý výpočet, protože offset je na čipech Intel 8086/8088 vždy šestnáctibitový. To znamená, že veškeré výpočty offsetu uvedené v předchozí tabulce za všech předpokladů vedou k hodnotám v rozsahu 0×0000 až 0×ffff a nikdy tedy nepřekročíme velikost segmentu.
3. Šestnáctibitové adresy na čipech druhé a třetí generace 80×86
Mikroprocesory druhé a třetí generace 80×86, tedy jak 80286, tak i 80386, sice interně počítají adresy odlišnými obvody, ovšem stále platí, že když se výpočty offsetu provádí se šestnáctibitovými registry (a pouze za tohoto předpokladu), bude výsledný offset vždy ležet v rozsahu 0×0000 až 0×ffff, tedy v rámci jediného segmentu. Ostatně si tuto vlastnost ukážeme na demonstračních příkladech, které budou své výsledky zobrazovat ve vizuální podobě.
Připomeňme si, že v grafickém režimu 13h karty VGA začíná obrazová paměť na segmentu 0×a000 a má velikost 320×200=64000 bajtů. Můžeme tedy snadno realizovat blokový přenos obrázku z RAM do VideoRAM, a to tak, že zdrojová data budou adresována přes dvojici registrů DS:SI (SI=source index) a cílová adresa bude uložena ve dvojici ES:DI (DI=destination index):
mov ax, cs mov ds, ax mov si, image ; nyni dvojice DS:SI obsahuje adresu prvniho bajtu v obrazku mov ax, 0xa000 ; (lze i PUSH 0xa000 + POP ES) mov es, ax xor di, di ; nyni dvojice ES:DI obsahuje adresu prvniho pixelu ve video RAM mov cx, 320*200/2 ; pocet zapisovanych 16bitovych slov (=dvojic pixelu)
Samotný blokový přenos zajistí instrukce REP MOVSW, která používá CX ve funkci počitadla a postupně zvyšuje indexové registry SI a DI:
rep movsw ; prenos celeho obrazku po 16bitovych slovech
Výsledkem by měl být celý obrázek (64000 bajtů) přenesený do obrazové paměti:

Obrázek 1: Výsledek přenosu celého obrázku do obrazové paměti.
Úplný zdrojový kód tohoto demonstračního příkladu vypadá následovně:
; Graficky rezim karty VGA s rozlisenim 320x200 pixelu. ; Vykresleni rastroveho obrazku s explicitnim prenosem po dvou bajtech. ; Pro blokovy prenos se pouziva instrukce REP MOVSW ; ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 286 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 mov ah, 0x4c ; cislo sluzby DOSu int 0x21 ; zavolani sluzby DOSu %endmacro ; vyprazdneni bufferu klavesnice a cekani na klavesu %macro wait_key 0 xor ax, ax ; cislo sluzby BIOSu int 0x16 ; zavolani sluzby BIOSu %endmacro ; nastaveni grafickeho rezimu %macro gfx_mode 1 mov ah, 0 ; cislo sluzby VGA BIOSu mov al, %1 ; cislo grafickeho rezimu int 0x10 ; zavolani sluzby BIOSu %endmacro ; paleta ve stupnich sedi %macro grayscale_palette 0 mov ax, 0x1010 ; cislo sluzby a podsluzby VGA BIOSu xor bl, bl ; index barvy next_dac: mov ch, bl ; prvni barvova slozka shr ch, 1 shr ch, 1 mov cl, ch ; druha barvova slozka mov dh, ch ; treti barvova slozka int 0x10 ; modifikace mapovani v DAC inc bl ; zvysit index v DAC jnz next_dac ; nastavit dalsi barvu, dokud nedosahneme hodnoty 256 %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: gfx_mode 0x13 ; nastaveni rezimu 320x200 s 256 barvami grayscale_palette ; nastaveni palety se stupni sedi mov ax, cs mov ds, ax mov si, image ; nyni dvojice DS:SI obsahuje adresu prvniho bajtu v obrazku mov ax, 0xa000 ; (lze i PUSH 0xa000 + POP ES) mov es, ax xor di, di ; nyni dvojice ES:DI obsahuje adresu prvniho pixelu ve video RAM mov cx, 320*200/2 ; pocet zapisovanych 16bitovych slov (=dvojic pixelu) rep movsw ; prenos celeho obrazku po 16bitovych slovech wait_key ; cekani na stisk klavesy exit ; navrat do DOSu ; pridani binarnich dat s rastrovym obrazkem image: incbin "image_320x200.bin"
4. Rozepsání programové smyčky pro blokový přenos mezi dvěma segmenty
Blokový přenos byl v předchozím příkladu realizován jedinou instrukcí:
rep movsw ; prenos celeho obrazku po 16bitovych slovech
Tuto instrukci si pro další účely můžeme rozepsat do programové smyčky, v níž se postupně načítají šestnáctibitová slova z adresy DS a ukládají se na adresu ES tak, jak to již bylo popsáno. Indexové registry se zvyšují o dvojku, protože přenos provádím po šestnácti bitech a nikoli po osmi bitech. A nakonec instrukce LOOP snižuje počitadlo v CX a provádí skok v případě, že se ještě nedosáhlo nuly:
move_loop: ; prenos celeho obrazku po 16bitovych slovech mov ax, ds:[si] ; nacteni dvou bajtu mov es:[di], ax ; ulozeni dvou bajtu add si, 2 ; posun offsetu add di, 2 loop move_loop ; opakujeme
Výsledkem bude naprosto stejný obrázek, i když samotný blokový přenos bude pomalejší (to ovšem bez profileru nepoznáme):

Obrázek 2: Výsledek blokového přenosu by měl být naprosto totožný s prvním obrázkem.
Opět si pro úplnost ukažme celý zdrojový kód tohoto příkladu:
; Graficky rezim karty VGA s rozlisenim 320x200 pixelu. ; Vykresleni rastroveho obrazku s explicitnim prenosem po dvou bajtech. ; Pro blokovy prenos se pouziva programova smycka ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 286 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 mov ah, 0x4c ; cislo sluzby DOSu int 0x21 ; zavolani sluzby DOSu %endmacro ; vyprazdneni bufferu klavesnice a cekani na klavesu %macro wait_key 0 xor ax, ax ; cislo sluzby BIOSu int 0x16 ; zavolani sluzby BIOSu %endmacro ; nastaveni grafickeho rezimu %macro gfx_mode 1 mov ah, 0 ; cislo sluzby VGA BIOSu mov al, %1 ; cislo grafickeho rezimu int 0x10 ; zavolani sluzby BIOSu %endmacro ; paleta ve stupnich sedi %macro grayscale_palette 0 mov ax, 0x1010 ; cislo sluzby a podsluzby VGA BIOSu xor bl, bl ; index barvy next_dac: mov ch, bl ; prvni barvova slozka shr ch, 1 shr ch, 1 mov cl, ch ; druha barvova slozka mov dh, ch ; treti barvova slozka int 0x10 ; modifikace mapovani v DAC inc bl ; zvysit index v DAC jnz next_dac ; nastavit dalsi barvu, dokud nedosahneme hodnoty 256 %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: gfx_mode 0x13 ; nastaveni rezimu 320x200 s 256 barvami grayscale_palette ; nastaveni palety se stupni sedi mov ax, cs mov ds, ax mov si, image ; nyni dvojice DS:SI obsahuje adresu prvniho bajtu v obrazku mov ax, 0xa000 ; (lze i PUSH 0xa000 + POP ES) mov es, ax xor di, di ; nyni dvojice ES:DI obsahuje adresu prvniho pixelu ve video RAM mov cx, 320*200/2 ; pocet zapisovanych 16bitovych slov (=dvojic pixelu) move_loop: ; prenos celeho obrazku po 16bitovych slovech mov ax, ds:[si] ; nacteni dvou bajtu mov es:[di], ax ; ulozeni dvou bajtu add si, 2 ; posun offsetu add di, 2 loop move_loop ; opakujeme wait_key ; cekani na stisk klavesy exit ; navrat do DOSu ; pridani binarnich dat s rastrovym obrazkem image: incbin "image_320x200.bin"
5. Offset přesahující hranici segmentu
V obou předchozích příkladech ležela první cílová adresa na začátku segmentu 0×a000. Konkrétně segmentový registr ES obsahoval hodnotu 0×a000 (segment) a registr DI nulu:
mov ax, 0xa000 ; (lze i PUSH 0xa000 + POP ES) mov es, ax xor di, di ; nyni dvojice ES:DI obsahuje adresu prvniho pixelu ve video RAM
Co se však stane v případě, že nastavíme segmentový registr na hodnotu 0×9800 a budeme ukládat data s offsetem 0×8000? Nejdříve nastavíme segmentový registr:
mov ax, 0x9800 mov es, ax xor di, di ; nyni ES:DI obsahuje adresu Video RAM-32kB
A následně upravíme programovou smyčku tak, aby se k obsahu registru DI přidal ještě offset 0×8000:
move_loop: ; prenos celeho obrazku po 16bitovych slovech mov ax, ds:[si] ; nacteni dvou bajtu mov es:[di+0x8000], ax ; ulozeni dvou bajtu, ovsem musime se posunouto 32kB nahoru add si, 2 ; posun offsetu add di, 2 loop move_loop ; opakujeme
Výsledný obrázek naznačuje, co se stalo. První polovina obrázku byla přenesena bez problémů, protože DI+0×8000 vracel šestnáctibitovou hodnotu menší než 0×10000 (tedy hodnotu ležící v segmentu 0×9800), ovšem druhá polovina byla přenesena nikoli do obrazové paměti, ale na začátek segmentu 0×9800 (což bychom dělat neměli – nevíme, co se zde nachází!).

Obrázek 3: Do VideoRAM se přenesla jen polovina obrázku, druhá polovina je „ztracena“ v adresovém rozsahu 0×98000 až 0×9ffff.
Platí tedy, že i když se segmenty 0×9800 a 0×a000 částečně (přesně polovinou) svého adresového prostoru překrývají, nemůžeme je jednoduše zaměnit s tím, že použijeme vhodně upravený offset – tento offset totiž nikdy nepřekročí šestnáctibitový rozsah.
Úplný zdrojový kód tohoto příkladu:
; Graficky rezim karty VGA s rozlisenim 320x200 pixelu. ; Vykresleni rastroveho obrazku s explicitnim prenosem po dvou bajtech. ; Pro blokovy prenos se pouziva programova smycka ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 286 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 mov ah, 0x4c ; cislo sluzby DOSu int 0x21 ; zavolani sluzby DOSu %endmacro ; vyprazdneni bufferu klavesnice a cekani na klavesu %macro wait_key 0 xor ax, ax ; cislo sluzby BIOSu int 0x16 ; zavolani sluzby BIOSu %endmacro ; nastaveni grafickeho rezimu %macro gfx_mode 1 mov ah, 0 ; cislo sluzby VGA BIOSu mov al, %1 ; cislo grafickeho rezimu int 0x10 ; zavolani sluzby BIOSu %endmacro ; paleta ve stupnich sedi %macro grayscale_palette 0 mov ax, 0x1010 ; cislo sluzby a podsluzby VGA BIOSu xor bl, bl ; index barvy next_dac: mov ch, bl ; prvni barvova slozka shr ch, 1 shr ch, 1 mov cl, ch ; druha barvova slozka mov dh, ch ; treti barvova slozka int 0x10 ; modifikace mapovani v DAC inc bl ; zvysit index v DAC jnz next_dac ; nastavit dalsi barvu, dokud nedosahneme hodnoty 256 %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: gfx_mode 0x13 ; nastaveni rezimu 320x200 s 256 barvami grayscale_palette ; nastaveni palety se stupni sedi mov ax, cs mov ds, ax mov si, image ; nyni dvojice DS:SI obsahuje adresu prvniho bajtu v obrazku mov ax, 0x9800 mov es, ax xor di, di ; nyni ES:DI obsahuje adresu Video RAM-32kB mov cx, 320*200/2 ; pocet zapisovanych 16bitovych slov (=dvojic pixelu) move_loop: ; prenos celeho obrazku po 16bitovych slovech mov ax, ds:[si] ; nacteni dvou bajtu mov es:[di+0x8000], ax ; ulozeni dvou bajtu, ovsem musime se posunouto 32kB nahoru add si, 2 ; posun offsetu add di, 2 loop move_loop ; opakujeme wait_key ; cekani na stisk klavesy exit ; navrat do DOSu ; pridani binarnich dat s rastrovym obrazkem image: incbin "image_320x200.bin"
6. Druhý příklad s offsetem, který přesahuje hranice segmentu
Možná ještě názornější bude následující demonstrační příklad, v němž budeme barvy pixelů ukládat do segmentu 0×a000, tedy skutečně přímo do obrazové paměti:
mov ax, 0xa000 mov es, ax xor di, di ; nyni ES:DI obsahuje adresu Video RAM+32kB
Nicméně si zvolíme posun o 320×100 bajtů od začátku segmentu s Video RAM, což znamená, že první vykreslený pixel bude začínat na začátku stého prvního řádku:
move_loop: ; prenos celeho obrazku po 16bitovych slovech mov ax, ds:[si] ; nacteni dvou bajtu posun equ 320*100 ; vypocet posunu o 100 obrazovych radku mov es:[di+posun], ax ; ulozeni dvou bajtu s posunem add si, 2 ; posun offsetu add di, 2 loop move_loop ; opakujeme
Výsledek bude následující – do spodní poloviny obrazovky se vykreslí prvních 100 řádků rastrového obrázku. Dalších 1536 pixelů se vykreslí do neviditelné části RAM (mezi offsety 64000 až 65535) a zbylé pixely (cca 95 obrazových řádků) „přetečou“ na začátek obrazovky:

Obrázek 4: Vykreslované pixely, pokud jsou ukládány do segmentu 0×a000, nikdy nepřekročí hranice Video RAM. Po dosažení konce segmentu se pixely začnou zapisovat opět od jeho začátku.
Opět jsme tedy nedokázali překročit hranici jednoho segmentu.
; Graficky rezim karty VGA s rozlisenim 320x200 pixelu. ; Vykresleni rastroveho obrazku s explicitnim prenosem po dvou bajtech. ; Pro blokovy prenos se pouziva programova smycka, ovsem pro posunuty segment. ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 286 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 mov ah, 0x4c ; cislo sluzby DOSu int 0x21 ; zavolani sluzby DOSu %endmacro ; vyprazdneni bufferu klavesnice a cekani na klavesu %macro wait_key 0 xor ax, ax ; cislo sluzby BIOSu int 0x16 ; zavolani sluzby BIOSu %endmacro ; nastaveni grafickeho rezimu %macro gfx_mode 1 mov ah, 0 ; cislo sluzby VGA BIOSu mov al, %1 ; cislo grafickeho rezimu int 0x10 ; zavolani sluzby BIOSu %endmacro ; paleta ve stupnich sedi %macro grayscale_palette 0 mov ax, 0x1010 ; cislo sluzby a podsluzby VGA BIOSu xor bl, bl ; index barvy next_dac: mov ch, bl ; prvni barvova slozka shr ch, 1 shr ch, 1 mov cl, ch ; druha barvova slozka mov dh, ch ; treti barvova slozka int 0x10 ; modifikace mapovani v DAC inc bl ; zvysit index v DAC jnz next_dac ; nastavit dalsi barvu, dokud nedosahneme hodnoty 256 %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: gfx_mode 0x13 ; nastaveni rezimu 320x200 s 256 barvami grayscale_palette ; nastaveni palety se stupni sedi mov ax, cs mov ds, ax mov si, image ; nyni dvojice DS:SI obsahuje adresu prvniho bajtu v obrazku mov ax, 0xa000 mov es, ax xor di, di ; nyni ES:DI obsahuje adresu Video RAM+32kB mov cx, 320*200/2 ; pocet zapisovanych 16bitovych slov (=dvojic pixelu) move_loop: ; prenos celeho obrazku po 16bitovych slovech mov ax, ds:[si] ; nacteni dvou bajtu posun equ 320*100 ; vypocet posunu o 100 obrazovych radku mov es:[di+posun], ax ; ulozeni dvou bajtu s posunem add si, 2 ; posun offsetu add di, 2 loop move_loop ; opakujeme wait_key ; cekani na stisk klavesy exit ; navrat do DOSu ; pridani binarnich dat s rastrovym obrazkem image: incbin "image_320x200.bin"
7. Chování mikroprocesoru Intel 80386 v reálném režimu
Po krátkém (ale jak dále uvidíme, tak důležitém) zopakování způsobu adresování mikroprocesorů Intel 8086/8088 se přeneseme o pár let dále, konkrétně k čipům 80386. Víme již, že tyto čipy nabízely programátorům další dva segmentové registry FS a GS, což bude důležité zejména v chráněném režimu. Ovšem pro nás zajímavější je fakt, že se rozšířily všechny pracovní registry ze šestnácti bitů na 32 bitů:
32bitový registr | Spodních 16 bitů | Rozdělení horní/dolní bajt | Funkce registru |
---|---|---|---|
EAX | AX | AH/AL | akumulátor |
EBX | BX | BH/BL | bázový registr |
ECX | CX | CH/CL | čítač |
EDX | DX | DH/DL | datový registr |
ESP | SP | ukazatel na vrchol zásobníku | |
EBP | BP | báze zásobníkového rámce | |
ESI | SI | indexový registr pro zdroj dat | |
EDI | DI | indexový registr pro cíl dat | |
EIP | IP | ukazatel na prováděnou instrukci |
Co to znamená v praxi? Nyní můžeme při adresování používat 32bitové offsety, a to i v reálném 16bitovém režimu! A i výpočet offsetu probíhá s využitím 32bitové sčítačky a nikoli sčítačky 16bitové. Znamená to tedy, že konečně můžeme překročit hranici 1MB a vlastně adresovat až 4GB RAM? Tak jednoduché nám to Intel neudělal, a to kvůli jedné prozatím nezmíněné vlastnosti 80286, která byla přenesena i do čipu 80386. Takže se v následující kapitole ještě jednou vraťme k 80286.
8. Skrytá část 80286: cache s deskriptory segmentů
V předchozím článku jsme si mj. řekli, že mikroprocesory 80286 byly prvními čipy z rodiny 80×86, které implementovaly chráněný režim (protected mode). V tomto novém režimu, do kterého se ale musely mikroprocesory explicitně přepnout, se změnilo adresování, zejména část týkající se segmentu. Nyní totiž hodnota uložená v segmentovém registru nespecifikovala přímou adresu (resp. její část), ale (poněkud zjednodušeně řečeno) index to tabulky deskriptorů (descriptor table). Tato tabulka obsahovala takzvané deskriptory, přičemž pro každý deskriptor bylo vyhrazeno osm bajtů, z nichž bylo ovšem na 80286 využito jen šest bajtů. Prozatím nás nebudou zajímat podrobnosti, jak přesně jsou hodnoty v tabulce deskriptorů uloženy, ale alespoň si řekněme, jaké informace každý deskriptor obsahuje:
Označení | Počet bitů | Stručný popis |
---|---|---|
Base | 24 | adresa začátku segmentu kdekoli v prostoru 16MB |
Limits | 16 | velikost segmentu (lze mít menší segment než 64kB) |
Control bits | 6 | řízení práv k segmentu |
DPL | 2 | úroveň oprávnění 0–3 (tzv. ring) |
Samozřejmě by nebylo efektivní, aby se při každém přístupu do paměti četlo těchto šest bajtů stále z tabulky deskriptorů. A ani to nebylo nutné, protože pokud každý záznam odpovídal hodnotě segmentu, bylo možné pro každou aktuálně používanou hodnotu segmentu uložit oněch šest bajtů do interních registrů mikroprocesoru – a na 80286 byly k dispozici čtyři segmentové registry, takže mikroprocesor musel obsahovat pouze 4×6 bajtů interní cache s hodnotami deskriptorů. Ovšem kvůli potřebám chráněného režimu (aby nebylo možné ochranu obejít) by tyto interní registry neměly být přístupné programátorům.
9. Cache s deskriptory segmentů v reálném režimu
Proč se však o deskriptorech zmiňujeme v souvislosti s běžným reálným režimem? Ukazuje se totiž, že tato cache má vliv i v reálném režimu, což je dosti překvapující, ale jedná se o vlastnost, která se projeví zejména u třetí generace 80×86. Na mikroprocesorech Intel 80286 se v reálném režimu (podle dostupných informací! – nejedná se totiž o oficiálně zdokumentované chování) využívá z každého ze čtyř deskriptorů bitové pole limits. V této šestnáctibitové hodnotě je uložena maximální hodnota platného offsetu. Co to znamená v praxi? Pokud by tato hodnota byla nastavena na řekněme 0×7fff, znamenalo by to, že se daný segment resp. jeho adresovatelná část, zmenší na offsety od 0×0000 do 0×7fff (včetně), zatímco při přístupu na offset 0×8000 až 0×ffff dojde k výjimce typu General protection fault (kterou však nemá v čistém DOSu kdo zpracovat!).

Obrázek 5: Výjimky dokážou zachytit takzvané DOS extendery; což ovšem platí pro programy pracující v chráněném režimu.
To je ovšem problematické chování, protože čipy 80286 vlastně nejsou zpětně kompatibilní s původní řadou 8086. Aby se zachovalo zdání kompatibility, jsou v průběhu inicializace 80286 limity všech čtyř deskriptorů uložených v cache nastaveny na hodnotu 0×ffff, takže se na první pohled zdá vše v pořádku, protože i 80286 dodržuje vlastnost zmíněnou výše – výpočty offsetů probíhají v šestnácti bitech a nikdy tedy nedokážou překročit právě onu hodnotu 0×ffff.
10. 32bitové adresy v reálném režimu
V předchozí kapitole jsme si naznačili, že za cenu jistého úsilí se Intelu podařilo zachovat zdání, že reálný režim je stále ten „starý dobrý“ reálný režim. Ale na další problémy již bylo zaděláno – a to ve chvíli, kdy se v rámci čipu 80386 přešlo na 32bitové offsetové registry (resp. všechny pracovní registry byly rozšířeny na 32bitů, včetně registrů použitých pro výpočet offsetu). Nastala totiž tato otázka – jak se má čip přesně chovat ve chvíli, kdy se provádí následující instrukce:
mov ax, [ebx + 0x12345678]

Obrázek 6: Schéma výpočtu adresy vypadalo skvěle: konečně můžeme využít celých 4GB a se stránkováním ještě více. Praxe bývala odlišná.
Zdroj: Intel 80386 Reference Programmer's Manual
Bylo možné definovat několik různých scénářů chování:
- Specifikuje se, že z 32bitových registrů se použije jen spodních 16 bitů a totéž pro konstanty
- Specifikuje se, že se v případě, že jakákoli část adresy přesáhne 16 bitů, vyhodí výjimka
- Specifikuje se, že se v případě, že výsledný offset přesáhne 16 bitů, vyhodí výjimka
- Ponechá se 32bitové chování (tedy něco, čeho lze dosáhnout nereálným režimem)
Vybrána nakonec byla druhá možnost, což znamenalo, že onen skvělý nový (drahý) čip, který byl v reklamách označován za 32bitovou revoluci, se stále v DOSu (a v mnoha překladačích) choval jako 80286. Navíc se přidala nová vlastnost, na kterou mohli narazit programátoři, kteří si přáli využít „dlouhé 32bitové adresy“ – při překročení hranice 64kB došlo buď k zamrznutí systému, nebo k jinému problému, a to v závislosti na konkrétní konfiguraci (zda je použit správce paměti, zda běží nějaký extender atd.).
11. Deskriptory segmentů na čipech 80386
I na čipech 80386 je v chráněném režimu použita tabulka deskriptorů. A opět platí, že přímo v mikroprocesorech 80386 existuje cache pro deskriptory odpovídající všem segmentovým registrům. Nyní je těchto deskriptorů šest a nikoli jen čtyři, a to z toho důvodu, že kromě původních segmentových registrů CS, DS, ES a SS byly přidány i dva nové segmentové registry nazvané FS a GS.
To je ovšem spíše kosmetická změna. Důležitější je, že nyní má deskriptor obsazených všech osm bajtů a nikoli jen šest bajtů. Proč tomu tak je? Zvětšil se počet bitů pro bázovou adresu segmentu, a to na plných 32 bitů (rozsah 4GB – opět je zde prostor pro novou A32 GATE namísto původní A20 GATE :-). A taktéž se zvětšil počet bitů pro limit, a to z původních 16 bitů (maximální limit 0×ffff) na 20 bitů, ovšem s tím, že se namísto bajtů může limit nastavit i v celých stránkách (to se přepíná dalším bitem).

Obrázek 7: Ze struktury bitových polí deskriptorů je patrné, jak se nové bity přidávaly k bitům definovaným již u čipů 80286
Zdroj: Intel 80386 Reference Programmer's Manual
Důležité je, že se limity opět projeví i v reálném režimu a Intel zachoval původní hodnotu limitů – tedy je zde zapsána hodnota 0×ffff. V praxi to tedy znamená, že překročení velikosti offsetu nad tuto hranici dojde k výjimce a tím pádem (obecně) k pádu aplikace pracující v reálném režimu.
12. Ukázka adresace 32bitovými registry v reálném režimu
Demonstrační příklad ze třetí kapitoly si můžeme snadno přepsat do podoby, ve které se použijí 32bitové přenosy:
mov cx, 320*200/4 ; pocet zapisovanych 32bitovych slov (=ctveric pixelu) rep movsd ; prenos celeho obrazku po 32bitovych slovech
Podle toho, zda je použit prefix 0×67, se navíc rozhoduje, zda budou adresy specifikovány ve dvojicích DS a ES nebo se použijí dvojice DS a ES.

Obrázek 8: Výsledek 32bitového přenosu by se neměl nijak lišit od šestnáctibitového přenosu.
Úplný zdrojový kód tohoto příkladu vypadá následovně:
; Graficky rezim karty VGA s rozlisenim 320x200 pixelu. ; Vykresleni rastroveho obrazku s explicitnim prenosem po ctyrech bajtech. ; Pro blokovy prenos se pouziva instrukce REP MOVSD ; ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 386 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 mov ah, 0x4c ; cislo sluzby DOSu int 0x21 ; zavolani sluzby DOSu %endmacro ; vyprazdneni bufferu klavesnice a cekani na klavesu %macro wait_key 0 xor ax, ax ; cislo sluzby BIOSu int 0x16 ; zavolani sluzby BIOSu %endmacro ; nastaveni grafickeho rezimu %macro gfx_mode 1 mov ah, 0 ; cislo sluzby VGA BIOSu mov al, %1 ; cislo grafickeho rezimu int 0x10 ; zavolani sluzby BIOSu %endmacro ; paleta ve stupnich sedi %macro grayscale_palette 0 mov ax, 0x1010 ; cislo sluzby a podsluzby VGA BIOSu xor bl, bl ; index barvy next_dac: mov ch, bl ; prvni barvova slozka shr ch, 1 shr ch, 1 mov cl, ch ; druha barvova slozka mov dh, ch ; treti barvova slozka int 0x10 ; modifikace mapovani v DAC inc bl ; zvysit index v DAC jnz next_dac ; nastavit dalsi barvu, dokud nedosahneme hodnoty 256 %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: gfx_mode 0x13 ; nastaveni rezimu 320x200 s 256 barvami grayscale_palette ; nastaveni palety se stupni sedi mov ax, cs mov ds, ax mov esi, image ; nyni dvojice DS:ESI obsahuje adresu prvniho bajtu v obrazku mov ax, 0xa000 ; (lze i PUSH 0xa000 + POP ES) mov es, ax xor edi, edi ; nyni dvojice ES:EDI obsahuje adresu prvniho pixelu ve video RAM mov cx, 320*200/4 ; pocet zapisovanych 32bitovych slov (=ctveric pixelu) rep movsd ; prenos celeho obrazku po 32bitovych slovech wait_key ; cekani na stisk klavesy exit ; navrat do DOSu ; pridani binarnich dat s rastrovym obrazkem image: incbin "image_320x200.bin"
13. Rozepsání programové smyčky: přenos po 32bitech, offsety jsou realizovány 32bitovými registry
Blokový přenos rep movsd si opět můžeme přepsat do podoby běžné programové smyčky. Nejdříve nastavíme zdrojové a cílové adresy, tentokrát ovšem použijeme 32bitové offsetové registry:
mov ax, cs mov ds, ax mov esi, image ; nyni dvojice DS:ESI obsahuje adresu prvniho bajtu v obrazku mov ax, 0xa000 ; (lze i PUSH 0xa000 + POP ES) mov es, ax xor edi, edi ; nyni dvojice ES:EDI obsahuje adresu prvniho pixelu ve video RAM
Dále nastavíme počet opakování smyčky:
mov cx, 320*200/4 ; pocet zapisovanych 32bitovych slov (=ctveric pixelu)
A nakonec nám zbývá realizace této smyčky. Opět si povšimněte použití 32bitových offsetů (ovšem ty nikdy nepřesáhnou limit 64kB segmentu):
move_loop: ; prenos celeho obrazku po 32bitovych slovech mov eax, ds:[esi] ; nacteni ctyr bajtu mov es:[edi], eax ; ulozeni ctyr bajtu add esi, 4 ; posun offsetu add edi, 4 loop move_loop ; opakujeme
Úplný zdrojový kód tohoto příkladu vypadá následovně:
; Graficky rezim karty VGA s rozlisenim 320x200 pixelu. ; Vykresleni rastroveho obrazku s explicitnim prenosem po ctyrech bajtech. ; Pro blokovy prenos se pouziva programova smycka ; ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 386 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 mov ah, 0x4c ; cislo sluzby DOSu int 0x21 ; zavolani sluzby DOSu %endmacro ; vyprazdneni bufferu klavesnice a cekani na klavesu %macro wait_key 0 xor ax, ax ; cislo sluzby BIOSu int 0x16 ; zavolani sluzby BIOSu %endmacro ; nastaveni grafickeho rezimu %macro gfx_mode 1 mov ah, 0 ; cislo sluzby VGA BIOSu mov al, %1 ; cislo grafickeho rezimu int 0x10 ; zavolani sluzby BIOSu %endmacro ; paleta ve stupnich sedi %macro grayscale_palette 0 mov ax, 0x1010 ; cislo sluzby a podsluzby VGA BIOSu xor bl, bl ; index barvy next_dac: mov ch, bl ; prvni barvova slozka shr ch, 1 shr ch, 1 mov cl, ch ; druha barvova slozka mov dh, ch ; treti barvova slozka int 0x10 ; modifikace mapovani v DAC inc bl ; zvysit index v DAC jnz next_dac ; nastavit dalsi barvu, dokud nedosahneme hodnoty 256 %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: gfx_mode 0x13 ; nastaveni rezimu 320x200 s 256 barvami grayscale_palette ; nastaveni palety se stupni sedi mov ax, cs mov ds, ax mov esi, image ; nyni dvojice DS:ESI obsahuje adresu prvniho bajtu v obrazku mov ax, 0xa000 ; (lze i PUSH 0xa000 + POP ES) mov es, ax xor edi, edi ; nyni dvojice ES:EDI obsahuje adresu prvniho pixelu ve video RAM mov cx, 320*200/4 ; pocet zapisovanych 32bitovych slov (=ctveric pixelu) move_loop: ; prenos celeho obrazku po 32bitovych slovech mov eax, ds:[esi] ; nacteni ctyr bajtu mov es:[edi], eax ; ulozeni ctyr bajtu add esi, 4 ; posun offsetu add edi, 4 loop move_loop ; opakujeme wait_key ; cekani na klavesu exit ; navrat do DOSu ; pridani binarnich dat s rastrovym obrazkem image: incbin "image_320x200.bin"
14. Přístup do obrazové paměti přes segment 0×0000 a 32bitový offset
Pokusme se nyní předchozí ukázkový příklad upravit takovým způsobem, aby se k Video RAM přistupovalo sice stále přes fyzické adresy 0×a0000–0×afff, ale nyní přes segment 0×0000. To ovšem znamená nutnost použití 32bitového offsetu. Úprava zdrojového kódu je snadná – vynulujeme registr ES a nastavíme offset do registru EDI:
mov ax, cs mov ds, ax mov esi, image ; nyni dvojice DS:ESI obsahuje adresu prvniho bajtu v obrazku xor ax, ax mov es, ax ; ES=0x0000 !!! mov edi, 0xa0000 ; nyni dvojice ES:EDI obsahuje adresu prvniho pixelu ve video RAM
Dále nastavíme počitadlo opakování smyčky, a to už běžným způsobem:
mov cx, 320*200/4 ; pocet zapisovanych 32bitovych slov (=ctveric pixelu)
A pokusíme se provést vlastní blokový přenos.
move_loop: ; prenos celeho obrazku po 32bitovych slovech mov eax, ds:[esi] ; nacteni ctyr bajtu mov es:[edi], eax ; ulozeni ctyr bajtu add esi, 4 ; posun offsetu add edi, 4 loop move_loop ; opakujeme
Chování aplikace se nyní může ubrat několika směry:
- V reálném režimu aplikace zamrzne (a uvidíme jen černou obrazovku)
- V nereálném režimu (a podle všeho ho nastaví i některé verze HIMEM.SYS) se obrázek přenese bez problémů
- V případě aktivního extenderu závisí na nastavení limitů, ale obecně dojde k pádu kvůli výjimce
- V případě aktivního režimu V86 (virtuální režim) opět závisí na nastavení limitů
- DOSBox limity nekontroluje a proto aplikace obrázek přenese bez problémů

Obrázek 9: Výjimka v chráněném režimu zachycená extenderem.
Úplný kód tohoto demonstračního příkladu vypadá následovně:
; Graficky rezim karty VGA s rozlisenim 320x200 pixelu. ; Vykresleni rastroveho obrazku s explicitnim prenosem po ctyrech bajtech. ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 386 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 mov ah, 0x4c ; cislo sluzby DOSu int 0x21 ; zavolani sluzby DOSu %endmacro ; vyprazdneni bufferu klavesnice a cekani na klavesu %macro wait_key 0 xor ax, ax ; cislo sluzby BIOSu int 0x16 ; zavolani sluzby BIOSu %endmacro ; nastaveni grafickeho rezimu %macro gfx_mode 1 mov ah, 0 ; cislo sluzby VGA BIOSu mov al, %1 ; cislo grafickeho rezimu int 0x10 ; zavolani sluzby BIOSu %endmacro ; paleta ve stupnich sedi %macro grayscale_palette 0 mov ax, 0x1010 ; cislo sluzby a podsluzby VGA BIOSu xor bl, bl ; index barvy next_dac: mov ch, bl ; prvni barvova slozka shr ch, 1 shr ch, 1 mov cl, ch ; druha barvova slozka mov dh, ch ; treti barvova slozka int 0x10 ; modifikace mapovani v DAC inc bl ; zvysit index v DAC jnz next_dac ; nastavit dalsi barvu, dokud nedosahneme hodnoty 256 %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: gfx_mode 0x13 ; nastaveni rezimu 320x200 s 256 barvami grayscale_palette ; nastaveni palety se stupni sedi mov ax, cs mov ds, ax mov esi, image ; nyni dvojice DS:ESI obsahuje adresu prvniho bajtu v obrazku xor ax, ax mov es, ax ; ES=0x0000 !!! mov edi, 0xa0000 ; nyni dvojice ES:EDI obsahuje adresu prvniho pixelu ve video RAM mov cx, 320*200/4 ; pocet zapisovanych 32bitovych slov (=ctveric pixelu) move_loop: ; prenos celeho obrazku po 32bitovych slovech mov eax, ds:[esi] ; nacteni ctyr bajtu mov es:[edi], eax ; ulozeni ctyr bajtu add esi, 4 ; posun offsetu add edi, 4 loop move_loop ; opakujeme wait_key ; cekani na klavesu exit ; navrat do DOSu ; pridani binarnich dat s rastrovym obrazkem image: incbin "image_320x200.bin"
15. Překročení limitu segmentu s využitím posunu adresy o konstantu
Taktéž se můžeme pokusit o překročení limitu segmentu „jen o kousek“, a to s využitím konstanty přičtené k registru EDI. Nyní tedy (například) nastavíme segmentový registr ES na hodnotu 0×9800, tj. 32kB před první adresou Video RAM a vynulujeme registr EDI:
mov ax, 0x9800 mov es, ax ; ES=0x9800 !!! xor edi, edi ; nyni ES:EDI obsahuje adresu Video RAM-32kB
Samotná programová smyčka pro provedení blokových přenosů se pochopitelně bude muset modifikovat, protože nyní k registru EDI přičteme konstantu 0×8000, abychom kompenzovali nižší adresu segmentu. Samotný EDI tedy nikdy nepřekročí hodnotu 0×ffff, čímž se zdánlivě vyhneme problému, na který jsme narazili v předchozím příkladu:
move_loop: ; prenos celeho obrazku po 32bitovych slovech mov eax, ds:[esi] ; nacteni ctyr bajtu mov es:[edi+0x8000], eax ; ulozeni ctyr bajtu, ovsem s offsetem add esi, 4 ; posun offsetu add edi, 4 loop move_loop ; opakujeme
V praxi ovšem po spuštění tohoto programu může dojít ke všem chováním, které již byly popsány v předchozí kapitole: od bezproblémového zobrazení rastrového obrázku přes zamrznutí aplikace až po pád po zachycení HW výjimky.
; Graficky rezim karty VGA s rozlisenim 320x200 pixelu. ; Vykresleni rastroveho obrazku s explicitnim prenosem po ctyrech bajtech. ; ;----------------------------------------------------------------------------- BITS 16 ; 16bitovy vystup pro DOS CPU 386 ; specifikace pouziteho instrukcniho souboru ;----------------------------------------------------------------------------- ; ukonceni procesu a navrat do DOSu %macro exit 0 mov ah, 0x4c ; cislo sluzby DOSu int 0x21 ; zavolani sluzby DOSu %endmacro ; vyprazdneni bufferu klavesnice a cekani na klavesu %macro wait_key 0 xor ax, ax ; cislo sluzby BIOSu int 0x16 ; zavolani sluzby BIOSu %endmacro ; nastaveni grafickeho rezimu %macro gfx_mode 1 mov ah, 0 ; cislo sluzby VGA BIOSu mov al, %1 ; cislo grafickeho rezimu int 0x10 ; zavolani sluzby BIOSu %endmacro ; paleta ve stupnich sedi %macro grayscale_palette 0 mov ax, 0x1010 ; cislo sluzby a podsluzby VGA BIOSu xor bl, bl ; index barvy next_dac: mov ch, bl ; prvni barvova slozka shr ch, 1 shr ch, 1 mov cl, ch ; druha barvova slozka mov dh, ch ; treti barvova slozka int 0x10 ; modifikace mapovani v DAC inc bl ; zvysit index v DAC jnz next_dac ; nastavit dalsi barvu, dokud nedosahneme hodnoty 256 %endmacro ;----------------------------------------------------------------------------- org 0x100 ; zacatek kodu pro programy typu COM (vzdy se zacina na 256) start: gfx_mode 0x13 ; nastaveni rezimu 320x200 s 256 barvami grayscale_palette ; nastaveni palety se stupni sedi mov ax, cs mov ds, ax mov esi, image ; nyni dvojice DS:ESI obsahuje adresu prvniho bajtu v obrazku mov ax, 0x9800 mov es, ax ; ES=0x9800 !!! xor edi, edi ; nyni ES:EDI obsahuje adresu Video RAM-32kB mov cx, 320*200/4 ; pocet zapisovanych 32bitovych slov (=ctveric pixelu) move_loop: ; prenos celeho obrazku po 32bitovych slovech mov eax, ds:[esi] ; nacteni ctyr bajtu mov es:[edi+0x8000], eax ; ulozeni ctyr bajtu, ovsem s offsetem add esi, 4 ; posun offsetu add edi, 4 loop move_loop ; opakujeme wait_key ; cekani na klavesu exit ; navrat do DOSu ; pridani binarnich dat s rastrovym obrazkem image: incbin "image_320x200.bin"
16. Naplnění cache s deskriptory přes „utajenou“ instrukci LOADALL
Jedinou oficiální cestou, jakou lze naplnit cache s deskriptory, je nastavení tabulek deskriptorů v operační paměti, přepnutí mikroprocesoru do chráněného režimu a načtení nových adres do segmentových registrů. V tomto případě se načtou příslušné hodnoty z tabulek deskriptorů do cache s deskriptory a nové bázové adresy segmentů i jejich limity začnou být platné. To jsou ovšem poměrně komplikované a taktéž pomalé operace, které navíc následně vyžadují přepnutí zpět do reálného režimu, což není (zejména v případě mikroprocesoru 80286 snadné a vlastně ani oficiálně možné – pro tento účel bylo nutné upravit interní architekturu IBM PC tak, aby se provedl reset mikroprocesoru). Ovšem nakonec se našla ještě zajímavější cesta, jak naplnit cache. Pro tento účel se totiž začala používat instrukce LOADALL.
Jedná se o instrukci, která nebyla oficiálně zdokumentována a byla společnosti Intel navržena primárně pro testovací účely prováděné ještě před instalací mikroprocesoru do základové desky. Ovšem to, že nějaká instrukce není zdokumentována, neznamená, že ji nelze použít, navíc v případě, že spolehlivě pracovala i na čipech vyráběných ostatními firmami (AMD, IBM). Navíc bylo možné tuto instrukci použít i v reálném režimu, bez nutnosti přepínání do režimu chráněného a zpět. V praxi se tedy tato instrukce začala používat dokonce i v samotném DOSu (HIMEM.SYS) a bylo již možné použít pro zavedení takzvaného nereálného režimu (unreal mode).
Na tomto místě je nutné zdůraznit, že instrukce LOADALL pro mikroprocesor 80286 je zcela odlišná od stejně pojmenované instrukce pro 80386. Dokonce se liší i operační kódy těchto instrukcí. Kód pro naplnění cache s deskriptory tedy musel zjistit, na jakém procesoru běží a poté použít odlišné větve v kódu.
17. LOADALL na mikroprocesorech 80286
Nejprve se podívejme, jakou operaci instrukce LOADALL provádí na mikroprocesorech Intel 80286. Operační kód této instrukce je 0f 05, přičemž se nespecifikují žádné operandy. Tato instrukce totiž očekává, že na adrese 0×00800 (tedy například 0080:0000 nebo 0000:0800) bude uloženo 102 bajtů, které se všechny přenesou do viditelných registrů mikroprocesoru, neviditelných registrů (nepřístupných programátorům) a taktéž se načte námi používaná cache s deskriptory (tedy čtyři deskriptory pro čtyři segmentové registry a další čtyři deskriptory pro adresy používané v chráněném režimu). Jedná se o relativně pomalou instrukci, protože její provedení trvá 195 hodinových cyklů. Ovšem díky ní lze snadno zpřístupnit jakýkoli blok rozšířené paměti, a to bez nutnosti blokové kopie dat (což je pochopitelně mnohem delší).
Hodnoty uložené od výše zmíněné adresy 0×00800 mají tento význam:
Adresa | Šířka dat | Stručný popis |
---|---|---|
0×00800 | 16 bitů | je vynulován |
0×00802 | 16 bitů | je vynulován |
0×00804 | 16 bitů | registr MSW |
0×00806 | 16 bitů | ? |
0×00808 | 16 bitů | je vynulován |
0×0080A | 16 bitů | je vynulován |
0×0080C | 16 bitů | je vynulován |
0×0080E | 16 bitů | je vynulován |
0×00810 | 16 bitů | je vynulován |
0×00812 | 16 bitů | je vynulován |
0×00814 | 16 bitů | je vynulován |
0×00816 | 16 bitů | registr TR |
0×00818 | 16 bitů | příznakový registr |
0×0081A | 16 bitů | registr IP |
0×0081C | 16 bitů | registr LDT |
0×0081E | 16 bitů | registr DS |
0×00820 | 16 bitů | registr SS |
0×00822 | 16 bitů | registr CS |
0×00824 | 16 bitů | registr ES |
0×00826 | 16 bitů | registr DI |
0×00828 | 16 bitů | registr SI |
0×0082A | 16 bitů | registr BP |
0×0082C | 16 bitů | registr SP |
0×0082E | 16 bitů | registr BX |
0×00830 | 16 bitů | registr DX |
0×00832 | 16 bitů | registr CX |
0×00834 | 16 bitů | registr AX |
0×00836 | 48 bitů | deskriptor pro ES |
0×0083C | 48 bitů | deskriptor pro CS |
0×00842 | 48 bitů | deskriptor pro SS |
0×00848 | 48 bitů | deskriptor pro DS |
0×0084E | 48 bitů | deskriptor pro GDT |
0×00854 | 48 bitů | deskriptor pro LDT |
0×0085A | 48 bitů | deskriptor pro IDT |
0×00860 | 48 bitů | deskriptor pro TSS |
0×00866 | konec | konec tabulky |
Pokud si tedy tento blok připravíme a budeme pouze měnit deskriptory od adresy 0X00836, je možné si postupně zpřístupnit veškerou nainstalovanou RAM. Není to řešení elegantní, ale funguje.
18. LOADALL na mikroprocesorech 80386
Stejně pojmenovaná (a stejně oficiálně nezdokumentovaná – vlastně ještě více utajovaná) je i instrukce LOADALL určená pro mikroprocesory 80386. Tato instrukce má odlišný operační kód 0F 07 a liší se i vyžadovaná struktura paměti, která je načtena do mikroprocesoru. Navíc se nyní explicitně udává adresa tohoto bloku paměti, a to konkrétně v registrech ES:EDI.
Zajímavé je, že bylo zjištěno, že ještě předtím, než se celá struktura načte do paměti, provede mikroprocesor čtení deseti 32bitových slov z adresy ES:EDI+0×100. Proč tomu tak je a kam se tato data ukládají, mi popravdě řečeno není známo. Nicméně se vraťme ke známým faktům – LOADALL opět načte obsahy registrů, kterých je na Intelu 80386 mnohem více. Taktéž se načtou deskriptory, které mají délku osmi bajtů a nikoli šesti bajtů (větší bázové adresy i limity). Podrobnosti o tomto mikroprocesoru (což byl pravděpodobně nejrevolučnější čip řady 80×86 až do doby, kdy vznikla 64bitová instrukční sada) si řekneme příště:
Šířka dat | Stručný popis |
---|---|
32 bitů | registr CR0 |
32 bitů | příznaky EFLAGS |
32 bitů | registr EIP |
32 bitů | registr EDI |
32 bitů | registr ESI |
32 bitů | registr EBP |
32 bitů | registr ESP |
32 bitů | registr EBX |
32 bitů | registr EDX |
32 bitů | registr ECX |
32 bitů | registr EAX |
32 bitů | registr DR6 |
32 bitů | registr DR7 |
32 bitů | registr TR |
32 bitů | registr LDT |
32 bitů | segmentový registr GS s výplní |
32 bitů | segmentový registr FS s výplní |
32 bitů | segmentový registr DS s výplní |
32 bitů | segmentový registr SS s výplní |
32 bitů | segmentový registr CS s výplní |
32 bitů | segmentový registr ES s výplní |
96 bitů | deskriptor pro registr TSS + výplň 32 bitů |
96 bitů | deskriptor pro registr IDTD + výplň 32 bitů |
96 bitů | deskriptor pro registr GDTD + výplň 32 bitů |
96 bitů | deskriptor pro registr LDTD + výplň 32 bitů |
96 bitů | deskriptor pro segmentový registr GS + výplň 32 bitů |
96 bitů | deskriptor pro segmentový registr FS + výplň 32 bitů |
96 bitů | deskriptor pro segmentový registr DS + výplň 32 bitů |
96 bitů | deskriptor pro segmentový registr SS + výplň 32 bitů |
96 bitů | deskriptor pro segmentový registr CS + výplň 32 bitů |
96 bitů | deskriptor pro segmentový registr ES + výplň 32 bitů |
19. Repositář s demonstračními příklady
Demonstrační příklady napsané v assembleru, které jsou určené pro překlad s využitím assembleru NASM, byly uloženy 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ář:
20. Odkazy na Internetu
- The Intel 8088 Architecture and Instruction Set
https://people.ece.ubc.ca/~edc/464/lectures/lec4.pdf - x86 Opcode Structure and Instruction Overview
https://pnx.tf/files/x86_opcode_structure_and_instruction_overview.pdf - x86 instruction listings (Wikipedia)
https://en.wikipedia.org/wiki/X86_instruction_listings - x86 assembly language (Wikipedia)
https://en.wikipedia.org/wiki/X86_assembly_language - Intel Assembler (Cheat sheet)
http://www.jegerlehner.ch/intel/IntelCodeTable.pdf - 25 Microchips That Shook the World
https://spectrum.ieee.org/tech-history/silicon-revolution/25-microchips-that-shook-the-world - Chip Hall of Fame: MOS Technology 6502 Microprocessor
https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-mos-technology-6502-microprocessor - Chip Hall of Fame: Intel 8088 Microprocessor
https://spectrum.ieee.org/tech-history/silicon-revolution/chip-hall-of-fame-intel-8088-microprocessor - Jak se zrodil procesor?
https://www.root.cz/clanky/jak-se-zrodil-procesor/ - Apple II History Home
http://apple2history.org/ - The 8086/8088 Primer
https://www.stevemorse.org/8086/index.html - flat assembler: Assembly language resources
https://flatassembler.net/ - FASM na Wikipedii
https://en.wikipedia.org/wiki/FASM - Fresh IDE FASM inside
https://fresh.flatassembler.net/ - MS-DOS Version 4.0 Programmer's Reference
https://www.pcjs.org/documents/books/mspl13/msdos/dosref40/ - DOS API (Wikipedia)
https://en.wikipedia.org/wiki/DOS_API - Bit banging
https://en.wikipedia.org/wiki/Bit_banging - IBM Basic assembly language and successors (Wikipedia)
https://en.wikipedia.org/wiki/IBM_Basic_assembly_language_and_successors - X86 Assembly/Bootloaders
https://en.wikibooks.org/wiki/X86_Assembly/Bootloaders - Počátky grafiky na PC: grafické karty CGA a Hercules
https://www.root.cz/clanky/pocatky-grafiky-na-pc-graficke-karty-cga-a-hercules/ - 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/ - Karta EGA: první použitelná barevná grafika na PC
https://www.root.cz/clanky/karta-ega-prvni-pouzitelna-barevna-grafika-na-pc/ - RGB Classic Games
https://www.classicdosgames.com/ - Turbo Assembler (Wikipedia)
https://en.wikipedia.org/wiki/Turbo_Assembler - Microsoft Macro Assembler
https://en.wikipedia.org/wiki/Microsoft_Macro_Assembler - IBM Personal Computer (Wikipedia)
https://en.wikipedia.org/wiki/IBM_Personal_Computer - Intel 8251
https://en.wikipedia.org/wiki/Intel_8251 - Intel 8253
https://en.wikipedia.org/wiki/Intel_8253 - Intel 8255
https://en.wikipedia.org/wiki/Intel_8255 - Intel 8257
https://en.wikipedia.org/wiki/Intel_8257 - Intel 8259
https://en.wikipedia.org/wiki/Intel_8259 - Support/peripheral/other chips – 6800 family
http://www.cpu-world.com/Support/6800.html - Motorola 6845
http://en.wikipedia.org/wiki/Motorola_6845 - The 6845 Cathode Ray Tube Controller (CRTC)
http://www.tinyvga.com/6845 - CRTC operation
http://www.6502.org/users/andre/hwinfo/crtc/crtc.html - The 6845 Cathode Ray Tube Controller (CRTC)
http://www.tinyvga.com/6845 - Motorola 6845 and bitwise graphics
https://retrocomputing.stackexchange.com/questions/10996/motorola-6845-and-bitwise-graphics - IBM Monochrome Display Adapter
http://en.wikipedia.org/wiki/Monochrome_Display_Adapter - Color Graphics Adapter
http://en.wikipedia.org/wiki/Color_Graphics_Adapter - Color Graphics Adapter and the Brown color in IBM 5153 Color Display
https://www.aceinnova.com/en/electronics/cga-and-the-brown-color-in-ibm-5153-color-display/ - The Modern Retrocomputer: An Arduino Driven 6845 CRT Controller
https://hackaday.com/2017/05/14/the-modern-retrocomputer-an-arduino-driven-6845-crt-controller/ - flat assembler: Assembly language resources
https://flatassembler.net/ - FASM na Wikipedii
https://en.wikipedia.org/wiki/FASM - Fresh IDE FASM inside
https://fresh.flatassembler.net/ - MS-DOS Version 4.0 Programmer's Reference
https://www.pcjs.org/documents/books/mspl13/msdos/dosref40/ - DOS API (Wikipedia)
https://en.wikipedia.org/wiki/DOS_API - IBM Basic assembly language and successors (Wikipedia)
https://en.wikipedia.org/wiki/IBM_Basic_assembly_language_and_successors - X86 Assembly/Arithmetic
https://en.wikibooks.org/wiki/X86_Assembly/Arithmetic - Art of Assembly – Arithmetic Instructions
http://oopweb.com/Assembly/Documents/ArtOfAssembly/Volume/Chapter6/CH06–2.html - ASM Flags
http://www.cavestory.org/guides/csasm/guide/asm_flags.html - Status Register
https://en.wikipedia.org/wiki/Status_register - Linux assemblers: A comparison of GAS and NASM
http://www.ibm.com/developerworks/library/l-gas-nasm/index.html - Programovani v assembleru na OS Linux
http://www.cs.vsb.cz/grygarek/asm/asmlinux.html - Is it worthwhile to learn x86 assembly language today?
https://www.quora.com/Is-it-worthwhile-to-learn-x86-assembly-language-today?share=1 - Why Learn Assembly Language?
http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language - Is Assembly still relevant?
http://programmers.stackexchange.com/questions/95836/is-assembly-still-relevant - Why Learning Assembly Language Is Still a Good Idea
http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html - Assembly language today
http://beust.com/weblog/2004/06/23/assembly-language-today/ - Assembler: Význam assembleru dnes
http://www.builder.cz/rubriky/assembler/vyznam-assembleru-dnes-155960cz - Programming from the Ground Up Book – Summary
http://savannah.nongnu.org/projects/pgubook/ - DOSBox
https://www.dosbox.com/ - The C Programming Language
https://en.wikipedia.org/wiki/The_C_Programming_Language - Hercules Graphics Card (HCG)
https://en.wikipedia.org/wiki/Hercules_Graphics_Card - Complete 8086 instruction set
https://content.ctcd.edu/courses/cosc2325/m22/docs/emu8086ins.pdf - Complete 8086 instruction set
https://yassinebridi.github.io/asm-docs/8086_instruction_set.html - 8088 MPH by Hornet + CRTC + DESiRE (final version)
https://www.youtube.com/watch?v=hNRO7lno_DM - Area 5150 by CRTC & Hornet (Party Version) / IBM PC+CGA Demo, Hardware Capture
https://www.youtube.com/watch?v=fWDxdoRTZPc - 80×86 Integer Instruction Set Timings (8088 – Pentium)
http://aturing.umcs.maine.edu/~meadow/courses/cos335/80×86-Integer-Instruction-Set-Clocks.pdf - Colour Graphics Adapter: Notes
https://www.seasip.info/VintagePC/cga.html - Restoring A Vintage CGA Card With Homebrew HASL
https://hackaday.com/2024/06/12/restoring-a-vintage-cga-card-with-homebrew-hasl/ - Demoing An 8088
https://hackaday.com/2015/04/10/demoing-an-8088/ - Video Memory Layouts
http://www.techhelpmanual.com/89-video_memory_layouts.html - Screen Attributes
http://www.techhelpmanual.com/87-screen_attributes.html - IBM PC Family – BIOS Video Modes
https://www.minuszerodegrees.net/video/bios_video_modes.htm - EGA Functions
https://cosmodoc.org/topics/ega-functions/#the-hierarchy-of-the-ega - Why the EGA can only use 16 of its 64 colours in 200-line modes
https://www.reenigne.org/blog/why-the-ega-can-only-use-16-of-its-64-colours-in-200-line-modes/ - How 16 colors saved PC gaming – the story of EGA graphics
https://www.custompc.com/retro-tech/ega-graphics - List of 16-bit computer color palettes
https://en.wikipedia.org/wiki/List_of16-bit_computer_color_palettes - Why were those colors chosen to be the default palette for 256-color VGA?
https://retrocomputing.stackexchange.com/questions/27994/why-were-those-colors-chosen-to-be-the-default-palette-for-256-color-vga - VGA Color Palettes
https://www.fountainware.com/EXPL/vga_color_palettes.htm - Hardware Level VGA and SVGA Video Programming Information Page
http://www.osdever.net/FreeVGA/vga/vga.htm - Hardware Level VGA and SVGA Video Programming Information Page – sequencer
http://www.osdever.net/FreeVGA/vga/seqreg.htm - VGA Basics
http://www.brackeen.com/vga/basics.html - Introduction to VGA Mode ‚X‘
https://web.archive.org/web/20160414072210/http://fly.srk.fer.hr/GDM/articles/vgamodex/vgamx1.html - VGA Mode-X
https://web.archive.org/web/20070123192523/http://www.gamedev.net/reference/articles/article356.asp - Mode-X: 256-Color VGA Magic
https://downloads.gamedev.net/pdf/gpbb/gpbb47.pdf - Instruction Format in 8086 Microprocessor
https://www.includehelp.com/embedded-system/instruction-format-in-8086-microprocessor.aspx - How to use „AND,“ „OR,“ and „XOR“ modes for VGA Drawing
https://retrocomputing.stackexchange.com/questions/21936/how-to-use-and-or-and-xor-modes-for-vga-drawing - VGA Hardware
https://wiki.osdev.org/VGA_Hardware - Programmer's Guide to Yamaha YMF 262/OPL3 FM Music Synthesizer
https://moddingwiki.shikadi.net/wiki/OPL_chip - Does anybody understand how OPL2 percussion mode works?
https://forum.vcfed.org/index.php?threads/does-anybody-understand-how-opl2-percussion-mode-works.60925/ - Yamaha YMF262 OPL3 music – MoonDriver for OPL3 DEMO [Oscilloscope View]
https://www.youtube.com/watch?v=a7I-QmrkAak - Yamaha OPL vs OPL2 vs OPL3 comparison
https://www.youtube.com/watch?v=5knetge5Gs0 - OPL3 Music Crockett's Theme
https://www.youtube.com/watch?v=HXS008pkgSQ - Bad Apple (Adlib Tracker – OPL3)
https://www.youtube.com/watch?v=2lEPH6Y3Luo - FM Synthesis Chips, Codecs and DACs
https://www.dosdays.co.uk/topics/fm_synthesizers.php - The Zen Challenge – YMF262 OPL3 Original (For an upcoming game)
https://www.youtube.com/watch?v=6JlFIFz1CFY - [adlib tracker II techno music – opl3] orbit around alpha andromedae I
https://www.youtube.com/watch?v=YqxJCu_WFuA - [adlib tracker 2 music – opl3 techno] hybridisation process on procyon-ii
https://www.youtube.com/watch?v=daSV5mN0sJ4 - Hyper Duel – Black Rain (YMF262 OPL3 Cover)
https://www.youtube.com/watch?v=pu_mzRRq8Ho - IBM 5155–5160 Technical Reference
https://www.minuszerodegrees.net/manuals/IBM/IBM_5155_5160_Technical_Reference_6280089_MAR86.pdf - a ymf262/opl3+pc speaker thing i made
https://www.youtube.com/watch?v=E-Mx0lEmnZ0 - [OPL3] Like a Thunder
https://www.youtube.com/watch?v=MHf06AGr8SU - (PC SPEAKER) bad apple
https://www.youtube.com/watch?v=LezmKIIHyUg - Powering devices from PC parallel port
http://www.epanorama.net/circuits/lptpower.html - Magic Mushroom (demo pro PC s DOSem)
http://www.crossfire-designs.de/download/articles/soundcards//mushroom.rar - Píseň Magic Mushroom – originál
http://www.crossfire-designs.de/download/articles/soundcards/speaker_mushroom_converted.mp3 - Píseň Magic Mushroom – hráno na PC Speakeru
http://www.crossfire-designs.de/download/articles/soundcards/speaker_mushroom_speaker.mp3 - Pulse Width Modulation (PWM) Simulation Example
http://decibel.ni.com/content/docs/DOC-4599 - Resistor/Pulse Width Modulation DAC
http://www.k9spud.com/traxmod/pwmdac.php - Class D Amplifier
http://en.wikipedia.org/wiki/Electronic_amplifier#Class_D - Covox Speech Thing / Disney Sound Source (1986)
http://www.crossfire-designs.de/index.php?lang=en&what=articles&name=showarticle.htm&article=soundcards/&page=5 - Covox Digital-Analog Converter (Rusky, obsahuje schémata)
http://phantom.sannata.ru/konkurs/netskater002.shtml - PC-GPE on the Web
http://bespin.org/~qz/pc-gpe/ - Keyboard Synthesizer
http://www.solarnavigator.net/music/instruments/keyboards.htm - FMS – Fully Modular Synthesizer
http://fmsynth.sourceforge.net/ - Javasynth
http://javasynth.sourceforge.net/ - Software Sound Synthesis & Music Composition Packages
http://www.linux-sound.org/swss.html - Mx44.1 Download Page (software synthesizer for linux)
http://hem.passagen.se/ja_linux/ - Software synthesizer
http://en.wikipedia.org/wiki/Software_synthesizer - Frequency modulation synthesis
http://en.wikipedia.org/wiki/Frequency_modulation_synthesis - Yamaha DX7
http://en.wikipedia.org/wiki/Yamaha_DX7 - Wave of the Future
http://www.wired.com/wired/archive/2.03/waveguides_pr.html - Analog synthesizer
http://en.wikipedia.org/wiki/Analog_synthesizer - Minimoog
http://en.wikipedia.org/wiki/Minimoog - Moog synthesizer
http://en.wikipedia.org/wiki/Moog_synthesizer - Tutorial for Frequency Modulation Synthesis
http://www.sfu.ca/~truax/fmtut.html - An Introduction To FM
http://ccrma.stanford.edu/software/snd/snd/fm.html - John Chowning
http://en.wikipedia.org/wiki/John_Chowning - I'm Impressed, Adlib Music is AMAZING!
https://www.youtube.com/watch?v=PJNjQYp1ras - Milinda- Diode Milliampere ( OPL3 )
https://www.youtube.com/watch?v=oNhazT5HG0E - Dune 2 – Roland MT-32 Soundtrack
https://www.youtube.com/watch?v=kQADZeB-z8M - Interrupts
https://wiki.osdev.org/Interrupts#Types_of_Interrupts - Assembly8086SoundBlasterDmaSingleCycleMode
https://github.com/leonardo-ono/Assembly8086SoundBlasterDmaSingleCycleMode/blob/master/sbsc.asm - Interrupts in 8086 microprocessor
https://www.geeksforgeeks.org/interrupts-in-8086-microprocessor/ - Interrupt Structure of 8086
https://www.eeeguide.com/interrupt-structure-of-8086/ - A20 line
https://en.wikipedia.org/wiki/A20_line - Extended memory
https://en.wikipedia.org/wiki/Extended_memory#eXtended_Memory_Specification_(XMS) - Expanded memory
https://en.wikipedia.org/wiki/Expanded_memory - Protected mode
https://en.wikipedia.org/wiki/Protected_mode - Virtual 8086 mode
https://en.wikipedia.org/wiki/Virtual_8086_mode - Unreal mode
https://en.wikipedia.org/wiki/Unreal_mode - DOS memory management
https://en.wikipedia.org/wiki/DOS_memory_management - Upper memory area
https://en.wikipedia.org/wiki/Upper_memory_area - Removing the Mystery from SEGMENT : OFFSET Addressing
https://thestarman.pcministry.com/asm/debug/Segments.html - Segment descriptor
https://en.wikipedia.org/wiki/Segment_descriptor - When using a 32-bit register to address memory in the real mode, contents of the register must never exceed 0000FFFFH. Why?
https://stackoverflow.com/questions/45094696/when-using-a-32-bit-register-to-address-memory-in-the-real-mode-contents-of-the - A Brief History of Unreal Mode
https://www.os2museum.com/wp/a-brief-history-of-unreal-mode/ - Segment Limits
https://wiki.osdev.org/Segment_Limits - How do 32 bit addresses in real mode work?
https://forum.osdev.org/viewtopic.php?t=30642 - The LOADALL Instruction by Robert Collins
https://www.rcollins.org/articles/loadall/tspec_a3_doc.html