Vývoj operačného systému/Bootloader po prvé - BIOS

Mysli slobodne. Uč sa slobodne. — Zo slobodnej knižnice Wikibooks ~ Wikiknihy.

V tejto kapitole si ukážeme, ako sa pracuje so softvérovými prerušenia BIOSu. Budeme sa sústrediť na vstup a výstup.

Každé prerušenie si zo sebou berie aj stav registrov (nerátajúc EIP - pozícia kódu a ESP-miesto uloženia stavu) a vracia ho nezmenený (mimo registrov vracajúcich hodnotu, napríklad stlačenú klávesu ), čo znamená že registre sú jedným zo spôsobov, ako sa dajú prerušeniu poslať dáta. Zvyčajne sa číslo funkcie ktorú chceme cez prerušenie zavolať ukladá do registra EAX alebo len do jeho časti (AX, AL|AH). V prípadne základných BIOSových rutín sa používa register AH.

Znakový výstup[upraviť]

Prerušenie na zobrazenie výstupu má číslo 16 (teda 0x10 hexadecimálne). Po zavolaní prerušenia sa hodnota (farba alebo znak) určená na vypísanie a pozícia na obrazovke upravia do formátu, ktorý akceptuje grafická karta. Následne sa zabezpečí vypísanie, zafarbenie a posunutie kurzoru. O udržiavanie obrazu na obrazovke sa už nestará prerušenie, ale grafická karta. Je nutné podotknúť že BIOSové prerušenia sa spolu s postupom grafických kariet veľmi nevyvíjali (BIOS dnes podporuje len z hľadiska kvality zastaralý štandard VGA, prípadne lepší štandard VBE, no nie je to žiadna sláva). Z toho hľadiska netreba od reálneho módu veľa očakávať. Nižšie je uvedený zoznam funkcií na základnú prácu s grafikou pomocou prerušenia 16.

Funkcie prerušenia 0x10[upraviť]

Číslo (hodnota registra AH) Názov Vstup Výstup Popis
00 Set video mode - nastav mód zobrazovania grafického výstupu AL=požadovaný video mód (pozri tabuľku nižšie) AL=stav módu (0x20 mód > 7, 0x30 módy 0-5 a 7, 0x3F mód 6)

alebo

AL=bajt módu radiča CRT monitoru

Nastaví konkrétny mód vyobrazovania dát na obrazovku.
02 Set cursor position - nastav pozíciu kurzora BH = číslo stránky, DH = riadok, DL = stĺpec Nastaví pozíciu kurzora v textovom móde na obrazovke
03 Get cursor position and shape - zober pozíciu a tvar kurzora BH = číslo stránky DH = riadok, DL = stĺpec, AX=0 Vyberie aktuálnu pozíciu kurzora na konkrétnej strane
05 Select active display page- vyber stránku na zobrazenie AL = číslo stránky Vyberie konkrétnu stranu vyobrazovania
08 Read character and attribute at cursor position - načítaj znak a atribút na pozícii kurzoru. BH = číslo stránky AH = farba, AL = znak Načíta znak a atribút(farba) z pozície kurzoru na konkrétnej stránke
09 Write character and attribute at cursor position - zapíš znak a atribút na aktuálnu pozíciu kurzoru. AL = znak, BH = číslo strany, BL = atribút (farba), CX = počet, koľkokrát sa má znak vypísať Vypíše (prepíše) znak a atribút na aktuálnu pozíciu kurzoru. Funkcia opačná k funkcii 08.
10 Write character only at cursor position - vypíš len znak na pozíciu kurzoru AL = znak, BH = číslo strany, CX = počet, koľkokrát sa má znak vypísať Vypíše (prepíše) znak na aktuálnu pozíciu kurzoru
11

Set background/border color - nastav farbu pozadia (alebo orámovania)

Set palette - nastav paletu

BH=0 (pre farbu pozadia), BL = farba pozadia/orámovania (orámovanie je dostupné len v textových módoch)

alebo

BH=1 (pre nastavenie palety), BL=identifikačné číslo palety (palette ID)

Nastaví farbu pozadia alebo paletu farieb na základe hodnoty registra BH.
14 Teletype output AL = znak, BH = číslo stránky, BL = farba (atribút) Vypíše znak na aktuálnu pozíciu kurzoru a posunie kurzor dopredu.
15 Get current video mode - načítaj aktuálny grafiký mód (mód vyobrazovania) AL = mód Funkcia opačná k funkcii 00.

Poznámka: "znaky" vypisované BIOSom sa držia ASCII tabuľky. Existujú nezmapované oblasti ASCII tabuľky, ktoré si prispôsobujú už jednotlivé firmy. Ak budete hľadať smajlíka, skúste čísla hneď na začiatku tabuľky ;)

Zobrazovacie módy BIOSu[upraviť]

Zobrazovacie (grafické) módy BIOSu (pre štandard VGA - dnes často podporovaný z dôvodov spätnej kompatibility). Rozlíšenie módu určuje v prípade pixelového módu šírku a výšku v bodoch, v prípade textového módu šírku a výšku v znakoch. (Samotný znak môže zaberať rôzny blok pixelov, v módoch VGA štandardne 9x16 alebo 8x8- mód 03.)

Poznámka: Dáta v tabuľke sú v desiatkovej sústave. Nula pred číslicami bola dodaná len pre zarovnanie. Nepoužívajte nulu pred číslami v programe - niektoré kompilátory by si mohli myslieť, že používate osmičkovú sústavu.

Číslo módu (vo fun.00 a 15=AL) Typ módu Rozlíšenie (podľa typu) Počet farieb
00 textový 40x25 16 odtieňov šedej
01 textový 40x25 16
02 textový 80x25 16 odtieňov šedej
03 textový 80x25 16
04 pixelový 320x200 4
05 pixelový 320x200 4 odtiene šedej
07 textový 80x25 2
13 pixelový 320x200 16
14 pixelový 640x200 16
15 pixelový 640x350 2
16 pixelový 640x350 16
17 pixelový 640x480 2
18 pixelový 640x480 16
19 pixelový 320x200 256

Poznámka: Mód s 256-timi farbami nepoužíva klasický spôsob vypočítavania farby z čísla. Namiesto toho používa číslo ako index v palete, ktorú si udržuje v pamäti grafická karta.

Poznámka: Mód s dvoma farbami (biela a čierna) sa niekedy zvykne označovať aj ako monochrómny (monochrome).


Príklady použítia funkcií[upraviť]

Funkcie 00 a 15[upraviť]

Nižšie uvedený kód overí, či je aktuálny mód 0 alebo 1 (rozlíšenie 40x25 znakov). Ak je to pravda, nastaví mód na 2 alebo 3 (v závislosti od pôvodného módu, proste pripočíta 2 a tým zachová farby).

BITS 16
mov ah, 15	; funkcia 15: načítaj aktuálny mód do AL
int 0x10	; zavolaj prerušenie
test al, 11111110 	;cez sito prepusti všetky bity okrem prvého
jnz .KONIEC		;nie je čo nastavovať
;ak je číslo módu 0 alebo 1, tak...
or al, 2	; mód 0 prestav na mód 2, mód 1 na mód 3 (zachovanie farieb)
mov ah, 00	; funkcia 00: nastav mód z registra AL
int 0x10	; nastav!

.KONIEC:

Funkcie 02 a 03[upraviť]

Tento kód simuluje (v reálnom použití to nie je potrebné) funkciu klávesy backspace, nie je však funkčný bez iných súčastí. Užívateľ môže posúvať kurzor dozadu (znak sa však nevymaže a tak ich môže prepisovať). Ak sú pozície x a y nulové, nachádzame sa v ľavom hornom okraji obrazovky a nemáme už miesto, kam by sme sa mohli posunúť. Poznámka: tento kód vychádza z toho, že šírka obrazovky je 80 stĺpcov (znakov). Pre funkčnosť by musel byť nastavený mód zodpovedajúci tejto požiadavky.

BITS 16
... 			; naplnenie registru AL
xor bh, bh			; ďalej v kóde chceme ukazovať na text na stránke 0

cmp al, '\b'		; rovná sa stisnutiu klávesy backspace?
jnz .pokracuj		; tak nič...
cmp dh, 0			; sme v riadku 0?
jnz .pracuj			; ak nie, všetko v poriadku
cmp dl, 0			; sme aj v stĺpci 0? - sme v pravom hornom kraji obrazovky
jz .pokracuj		; ak áno, tak nič nevymazuj - nie je čo
	mov ah, 03	; funkcia 03: zisti aktuálnu pozíciu kurzoru
	int 0x10	; zavolaj prerušenie

	dec dl		; x = x - 1
	jnz .nastav	; x!=0 ? ak sa nerovná, nastav kurzor
	mov dl, 79	; x = pravý okraj obrazovky
	dec dh		; y = y - 1 = o riadok vyššie

	.nastav:
	mov ah, 02	; funkcia 02: nastav pozíciu kurzoru
	int 0x10	; zavolaj prerušenie

.pokracuj:

Funkcia 05[upraviť]

Nasledujúci kód je niekedy dobré umiestniť na začiatok rozsiahlejších vypisovacích funkcií pre prípad, že by sa stránka na ktorú sa text vypisoval v inej časti programu zmenila. Tento kód nastaví stránku 0 ako aktívnu (bude sa zobrazovať na obrazovke).

BITS 16
mov ah, 5
xor al, al
int 0x10	; zavolaj prerušenie

Funkcie 08 a 09[upraviť]

Tento program má za úlohu skontrolovať všetky znaky na obrazovke, či sú znakom '$'. Ak ním sú, vymení ich za znak '€'.

xor bh, bh ;stránka 0
xor dh, dh
xor dl, dl ;x=y=0: ľavý horný roh obrazovky
mov cx, 1 ;znak chceme vypísať len raz

.cyklus:
cmp dl, 80			;sme za posledným stĺpcom?
jnz .over_riadok	;ak nie, skontroluj riadok
xor dl, dl			;ak áno, posuň kurzor na začiatok...
inc dh				;... nového riadka
.over_riadok:
cmp dh, 25			;sme za posledným riadkom?
jz .KONIEC			;už sme spracovali všetko, čo sa dalo

	mov ah, 02		;nastav kurzor
	int 0x10		;ideš!
	mov ah, 08		;funkcia 08: načítaj znak a farbu na pozícii kurzoru
	int 0x10		;čítaj!

	cmp al, '$'		;je to dolár?
	jnz .dalej		;ak nie, pokračuj na ďalší stĺpec
	mov al, '€'		;nastav znak na '€'
	mov bl, ah		;zachovaj prečítanú farbu
	mov ah, 09		;funkcia 09: zapíš znak a farbu na pozíciu kurzoru
	int 0x10		;zapíš!

	.dalej:
	inc dl			;posuň kurzor na ďalší stĺpec (znak v riadku)
	jmp .cyklus

.KONIEC:

Funkcia 10[upraviť]

Následný kód je poupravená verzia kódu pre funkcie 02 a 03. Tento kód v reakcii na znak '\b' (backspace) zároveň pred posunutím kurzoru dozadu znak vymaže (nahradí medzerou, znak 0 je ten spomínaný smajlík :) )

BITS 16
... 			; naplnenie registru AL
xor bh, bh			; ďalej v kóde chceme ukazovať na text na stránke 0
xor cx, cx

cmp al, '\b'		; rovná sa stisnutiu klávesy backspace?
jnz .pokracuj		; tak nič...
cmp dh, 0			; sme v riadku 0?
jnz .pracuj			; ak nie, všetko v poriadku
cmp dl, 0			; sme aj v stĺpci 0? - sme v pravom hornom kraji obrazovky
jz .pokracuj		; ak áno, tak nič nevymazuj - nie je čo
	mov ah, 03	; funkcia 03: zisti aktuálnu pozíciu kurzoru
	int 0x10	; zavolaj prerušenie

	mov ah, 09
	mov al, ' ' ; medzera, alebo hexadecimálne 0x20
	int 0x10	; zapíš

	dec dl		; x = x - 1
	jnz .nastav	; x!=0 ? ak sa nerovná, nastav kurzor
	mov dl, 79	; x = pravý okraj obrazovky
	dec dh		; y = y - 1 = o riadok vyššie

	.nastav:
	mov ah, 02	; funkcia 02: nastav pozíciu kurzoru
	int 0x10	; zavolaj prerušenie

.pokracuj:

Funkcia 14[upraviť]

Tento kód vypíše reťazec ukončený nulou (null-terminated string, štandard pre reťazce jazyka C - nie je potrebné držať informáciu o dĺžke).

BITS 16

mov si, retazec
call vypis
....
vypis:
	mov al, byte [ds:si]
	test al, al
	jz .koniec

	mov ah, 14
	int 0x10
	inc si
	jmp vypis

	.koniec:
	ret
...
retazec: db "Vitajte v realnom mode!", 0x0D, 0x0A, 0

Poznámka: Vyššia polovica ASCII tabuľky je často neštandardná. Diakritika nemusí byť podporovaná.

Podrobné zdroje[upraviť]

Znakový vstup[upraviť]

Otázka vstupu bývala v minulosti dosť spletitá. Existovalo viacero druhov klávesníc, ktoré sa odlišovali nielen zo softvérového hľadiska, ale aj z hľadiska hardvérového (rôzne druhy klávesníc mali rôzne konektory). Pred príchodom portu USB sa značne rozšírili pripojenia PS/2 (Personal System/2 od spoločnosti IBM). Počítače PS/2 mali podobné, no mechanicky a farebne rozdielne pripojenia pre myš (zelená) a klávesnicu (fialová). Ak ste zapojili myš do portu na klávesnicu alebo naopak, zariadenie nefungovalo. Pretože sa nejednalo o zariadenie pripojiteľné za behu (pluggable, hot-pugging), bolo treba konektory správne zapojiť a počítač reštartovať. Tieto zariadenia boli navrhnuté s dvoma radičmi. Prvý sa nachádzal na klávesnici a nazýval sa keyboard encoder. Druhý sa nachádzal na základnej doske a nazýval sa keyboard controller. Kým prvé zariadenie lokalizovalo stlačenú klávesu a informovalo ďalej, druhé zariadenie sa zaoberalo správou toho prvého. Keyboard controller po nejakom čase zrástol so základnou doskou (ako jej obvod).

Klávesnice PS/2 sa ujali a po príchode konektorov USB sa hneď nové návrhy nevymýšľali. V nových počítačoch (BIOS) sa preto nachádzalo premostenie, ktoré toto prepojenie umožňovalo. Z celkových funkcií klávesníc PS/2 sa vynechali len niektoré (napríklad scroll lock), inak si s klávesnicou PS/2 bez problémov vystačíte.

Prerušenie 0x16[upraviť]

Klávesnica posiela dva signály: press (stlačenie) a release (uvoľnenie). Každá klávesa (okrem zopár výnimiek) má svoj kód klávesy (scan code) pre obidve situácie. Existuje niekoľko súborov kódov kláves, a je na BIOSe na ktorom z nich sa s klávesnicou "dohodne". BIOS si pri načítavaní znakov z klávesnice dopredu udržiava informácie vo vlastnom bufferi (zozname stlačených kláves). Zavolaním špecifickej funkcie prerušenia sa pracuje s týmto bufferom, prípadne sa čaká na ďalší vstup.

Zoznam dôležitých funkcií prerušenia 0x16
Číslo funkcie (AH) Popis Vstup Výstup
00 Načíta stlačenú klávesu. Ak je zoznam stlačených kláves prázdny, na stlačenie si počká. AL=znak podľa ASCII tabuľky,

AH=kód stlačenej klávesy (press scan code), špecifický identifikátor klávesy na klávesnici (ASCII tabuľka nemusí mať všetky klávesy zmapované, niektoré znaky sa nedajú vyobraziť. Jedná sa o dáta priamo z klávesnice.).

01 Skontroluje, či boli stlačené nejaké klávesy od posledného čítania. ZF=1 ak nebola stlačená žiadna klávesa, inak 0.

V prípade stlačenia AL=znak podľa ASCII tabuľky, AH=kód klávesy (scan code)

02 Načíta stav špeciálnych kláves (SHIFT, ALT, CTRL, INSERT...) AL=stav špeciálnych kláves (pozri tabuľku nižšie)
03 Nastaví takzv. autorepeat, teda čas a interval, v ktorom sa má opakovať signál stlačenia klávesy ak je klávesa držaná dole po dlhší čas AL=05,

BH[1]=hodnota n predstavujúca zlomok sekúnd, ktorý sa má počkať kým sa začne opakovanie signálu stlačenia. Platí, že dĺžka vyčkávania je s kde .

BL[1]=hodnota , na základe ktorej sa dá vypočítať počet opakovaní stlačenia vykonaných za sekundu. Hodnoty sú skôr tabuľkové, no približne platia aj tieto dva vzorce:

05 Pridaj stlačenú klávesu na koniec zoznamu (prečíta sa ako posledná) CL=znak podľa ASCII tabuľky, CH=kód klávesy

Poznámka: BIOS neoveruje, či je hodnota CH správna. Hodnota sa uloží a keď na ňu príde rad, vyberie sa bez akejkoľvek práce s hodnotou. Na chybné dáta tak môže prísť až program spracúvajúci vstup zachytený BIOSom.

18 Načíta rozšírený stav špeciálnych kláves (pravý ALT, ľavý ALT, pravé CTRL, INSERT...) AX=rozšírený stav špeciálnych kláves (pozri tabuľku nižšie)
  1. 1,0 1,1 Niektoré zdroje majú funkciu registrov BH a BL uvedenú naopak

Stav špeciálnych kláves[upraviť]

Bit Stav špeciálnych kláves (funkcia 02) Rozšírený stav špeciálnych kláves (funkcia 18)
AH 0 Ľavá klávesa CTRL (stlačená)
1 Ľavý ALT (stlačený)
2 Pravá klávesa CTRL (stlačená)
3 Pravá klávesa ALT (stlačená)
4 Klávesa Scoll Lock (práve stláčaná)
5 Klávesa Num Lock (práve stláčaná)
6 Klávesa Caps Lock (práve stláčaná)
7 Klávesa SysRq (stlačená) - dnes aj nedodávaná (alebo dodávaná vo forme PrtScr, Fn+PrtScr)
AL 0 Pravý SHIFT (stlačený)
1 Ľavý SHIFT (stlačený)
2 Ľavá alebo pravá klávesa CTRL (stlačená)
3 Ľavá alebo pravá (na niektorých strojoch len ľavá) klávesa ALT (stlačená)
4 Klávesa Scoll Lock (aktivovaná)
5 Klávesa Num Lock (aktivovaná)
6 Klávesa Caps Lock (aktivovaná)
7 Klávesa Insert Lock (aktivovaná)

Príklady použitia funkcií[upraviť]

Funkcia 00[upraviť]

Nasledujúci kód načíta vstup z klávesnice a priamo ho vypíše na obrazovku (na aktuálnu pozíciu kurzoru).

BITS 16
start:
	xor ah, ah
	int 0x16
	mov ah, 0Eh
	int 0x10

	jmp start

Funkcie 02 a 18[upraviť]

Tento kód je uzavretý v nekonečnej slučke do času, keď bude stlačený pravý a ľavý alt. V prípade stlačenia obidvoch kláves sa vypíše správa "Dovidenia!" a vykonávanie sa zastaví.

BITS 16
start:
	.cyklus:
	mov ah, 02		;funkcia 02: načítaj stav špeciálnych kláves
	int 0x16		;načítaj!
	and al, 10
	cmp al, 10		;sú bity 3 (2^3) a 1 (2^1) nastavené (klávesy pravý a ľavý alt stlačené)?
	jne .cyklus		;ak nie, normálne pokračuj

	mov ax, 0x7C0
	mov ds, ax
	mov si, dovidenia
	call retazec

	cli				;zakáž prerušenia
	hlt				;zastav vykonávanie

retazec:
	xor bh, bh
	mov ah, 0x0E
.cyklus:
	mov al, byte [ds:si]
	test al, al
	jz .koniec
	int 0x10

	inc si
	jmp .cyklus

	.koniec:
	ret

dovidenia: db 0x0D, 0x0A, "Dovidenia!", 0

Funkcia 03[upraviť]

Kód nižšie nastaví dobu vyčkávania pred opakovaním stlačenia (BH) na jednu sekundu a frekvenciu opakovania približne na 7.5Hz.

BITS 16
start:
	mov ah, 03		;funkcia 03: nastavenie 'typematic delay' a 'typematic rate'
	mov al, 05		;nastavenie hodnôt
	mov bh, 3		;3+1/4 = 1s
	mov bl, 0x10	;približne 7.5 Hz
	int 0x16		;prerušenie 0x16: rutiny práce s klávesnicou

	cli				;zakáž prerušenia
	hlt				;zastav vykonávanie

Funkcia 05[upraviť]

Funkcia 05 má skôr využitie ako bočná systémová podpora, keď je nutné poslať vykonávajúcemu sa programu vstup zo systému napríklad kvôli nejakej udalosti. Systém pridávania je jednoduchý, no netreba zabúdať, že klávesa sa umiestni až na koniec zoznamu načítaných znakov (nebude prijatá prednostne).

BITS 16
	mov ah, 05		;funkcia 05: pridanie znaku na koniec zachyteného vstupu
	xor ch, ch		;kód klávesy=0
	mov cl, 65 		;znak podľa ASCII tabuľky=65='A'
	int 0x16		;prerušenie 0x16: rutiny práce s klávesnicou

Podrobné zdroje[upraviť]

Pozri aj[upraviť]