DOS BOOT TUT


Pisanie boot-sektorow
Autor: Bogdan Drozdowski, bogdandr (at) op.pl


Gdy juz choc srednio znacie assemblera, to po pewnym czasie pojawiaja sie
pytania (moga one byc spowodowane tym, co uslyszeliscie na grupach
dyskusyjnych lub Wasza wlasna ciekawoscia):

- Co sie dzieje, gdy ma zostac uruchomiony jest system operacyjny?
- Skad BIOS ma wiedziec, ktora czesc systemu uruchomic?
- Jak BIOS odroznia systemy operacyjne, aby moc je uruchomic?

Odpowiedz na pytanie 2 brzmi: nie wie. Odpowiedz na pytanie 3 brzmi: wcale.
Wszystkie Wasze watpliwosci rozwieje odpowiedz na pytanie 1.


Gdy zakonczyl sie POST (Power-On Self Test), wykrywanie dyskow i innych
urzadzen, BIOS przystepuje do czytania pierwszych sektorow tych urzadzen,
na ktorych ma byc szukany system operacyjny (u mnie jest ustawiona
kolejnosc: CD-ROM, stacja dyskietek, dysk twardy).

Gdy znajdzie sektor odpowiednio zaznaczony: bajt nr 510 = 55h i bajt
511 = AAh (pamietajmy, ze 1 sektor ma 512 bajtow, a liczymy od zera),
to wczytuje go pod adres bezwzgledny 07C00h i uruchamia kod w nim zawarty
(po prostu wykonuje JMP). Nie nalezy jednak polegac na tym, ze CS = 0 i
IP=7C00h (choc najczesciej tak jest).


To wlasnie boot-sektor jest odpowiedzialny za ladowanie odpowiednich czesci
wlasciwego systemu operacyjnego. Na komputerach z wieloma systemami
operacyjnymi sprawa tez nie jest tak bardzo skomplikowana. Pierwszy sektor
dysku twardego, zwany Master Boot Record (MBR), uruchamia program ladujacy
(tzw. Boot Manager, jak LILO czy GRUB), ktory z kolei uruchamia boot-sektor
wybranego systemu operacyjnego.



My oczywiscie nie bedziemy operowac na dyskach twardych, gdyz byloby to
niebezpieczne. Z dyskietkami zas mozna ekperymentowac do woli...
A instrukcja jest prosta: umieszczamy nasz programik w pierwszym sektorze
dyskietki, zaznaczamy go odpowiednimi ostatnimi bajtami i tyle.
No wlasnie... niby proste, ale jak o tym pomyslec to ani to pierwsze, ani to
drugie nie jest sprawa banalna.


Do zapisania naszego bootsektorka na dyskietke mozemy oczywiscie uzyc
"gotowcow" - programow typu rawwrite itp. Ma to pewne zalety - program byl
juz uzywany przez duza liczbe osob, jest sprawdzony i dziala.

Ale cos by bylo nie tak, gdybym w kursie programowania w assemblerze kazal
Wam uzywac cudzych programow. Do napisania sowjego wlasnego programu
zapisujacego dany plik w pierwszy sektor dyskietki w zupelnosci wystarczy
Wam wiedza uzyskana po przeczytaniu czesci mojego kursu poswieconej
operacjom na plikach wraz z tym (wyciag oczywiscie ze Spisu Przerwan
Ralfa Brown'a):

============================
INT 13 - DISK - WRITE DISK SECTOR(S)
AH = 03h
AL = number of sectors to write (must be nonzero)
CH = low eight bits of cylinder number
CL = sector number 1-63 (bits 0-5)
high two bits of cylinder (bits 6-7, hard disk only)
DH = head number
DL = drive number (bit 7 set for hard disk)
ES:BX -> data buffer
Return: CF set on error
CF clear if successful
============================


Jak widac, sprawa juz staje sie prosta. Oczywiscie, AL=1 (bo zapisujemy
1 sektor), DX=0 (bo stacja ma 2 glowice, a pierwsza ma numer 0, zas numer
dysku 0 wskazuje stacje A:), CX=1 (bo numery sektorow zaczynaja sie od 1,
a zapisujemy w pierwszym cylindrze i ma on numer 0).

Tak wiec, schemat jest taki:
- Otworz plik
- Przeczytaj z niego 512 bajtow do pamieci
- Zapisz je na dyskietce
- Zamknij plik
Sprawa jest tak prosta, ze tym razem nie podam "gotowca".


Gdy juz mamy program zapisujacy bootsektor na dyskietke, trzeba sie postarac
o to, aby nasz programik (ktory ma stac sie tym bootsektorem) mial
dokladnie 512 bajtow i aby 2 ostatnie jego bajty to 55h, AAh.

Oczywiscie, nie bedziemy recznie dokladac tylu bajtow, ile trzeba, aby
dopelnic nasz program do tych 512. Zrobi to za nas kompilator. Wystarczy
po calym kodzie i wszystkich danych, na szarym koncu, umiescic takie cos
(NASM/FASM):

times 510 - ($ - start) db 0
dw 0aa55h

Dla TASMa powinno to wygladac mniej wiecej tak:

db 510 - ($ - offset start) dup (0)
dw 0aa55h
end start


To wyrazenie mowi tyle: od biezacej pozycji w kodzie odejmij pozycje poczatku
kodu (tym samym obliczajac dlugosc calego kodu), otrzymana liczbe odejmij
od 510 - i doloz tyle wlasnie bajtow zerowych. Gdy juz mamy program dlugosci
510 bajtow, to dokladamy jeszcze znacznik i wszystko jest dobrze.

Jest jednak jeszcze jedna sprawa, o ktorej nie wspomnialem - ustawienie DS i
wartosci "org" dla naszego kodu. Otoz, jesli stwierdzimy, ze nasz kod
powinien zaczynac sie od offsetu 0 w naszym segmencie, to ustawmy sobie
"org 0" i DS=07C0h (tak, ilosc zer sie zgadza), ale mozemy tez miec
"org 7C00h" i DS=0. Zadne z tych nie wplywa w zaden sposob na dlugosc
otrzymanego programu, a nalezy o to zadbac, gdyz nie mamy gwarancji, ze DS
bedzie pokazywal na nasze dane po uruchomieniu bootsektora.


Teraz, uzbrojeni w niezbedna wiedze, zasiadamy do pisania kodu naszego
bootsektora. Nie musi to byc cos wielkiego - tutaj pokaze cos, co w lewym
gornym rogu ekranu pokaze cyfre "1" (o bezposredniej manipulacji ekranem
mozecie przeczytac w moim innym artykule) i po nacisnieciu dowolnego
klawisza zresetuje komputer (na jeden ze sposobow podanych w jeszcze
innym artykule...).


Oto nasz kod (NASM):

======================================
; nasm -o boot.bin -f bin boot.asm

org 7c00h ; lub "org 0"

start:
mov ax, 0b800h
mov es, ax ; ES = segment pamieci ekranu

mov byte [es:0], '1' ; piszemy '1'

xor ah, ah
int 16h ; czekamy na klawisz

mov bx, 40h
mov ds, bx
mov word [ds:72h], 1234h ; 40h:72h = 1234h - wybieramy
; goracy reset

jmp 0ffffh:0000h ; reset

times 510 - ($ - start) db 0 ; dopelnienie do 510 bajtow
dw 0aa55h ; znacznik
======================================


Nie bylo to dlugie ani trudne, prawda? Rzecz jasna, nie mozna w bootsektorach
uzywac zadnych przerwan systemowych, np. DOSowego int 21h, bo zaden system
po prostu nie jest uruchomiony i zaladowany. Tak napisany programik
kompilujemy do formatu binarnego. W TASMie wygladaloby to jakos tak
(po dodaniu w programie dyrektyw ".model tiny", ".code", ".8086" i
"end start"):

tasm bootsec1.asm
tlink bootsec1.obj,bootsec1.bin /t

Po kompilacji umieszczamy go na dyskietce przy uzyciu programu napisanego juz
przez nas wczesniej. Resetujemy komputer (i upewniamy sie, ze BIOS sprobuje
uruchomic system z dyskietki), wkladamy dyskietke i.... cieszymy sie swoim
dzielem (co prawda ta jedynka bedzie malo widoczna, ale rzeczywiscie
znajduje sie na ekranie).



Zauwazcie tez, ze ani DOS ani Windows nie rozpoznaje juz naszej dyskietki,
mimo iz przedtem byla sformatowana. Dzieje sie tak dlatego, ze w
bootsektorze umieszczane sa informacje o dysku.


"Prawidlowy" DOSowy/Windowsowy bootsektor powinien sie zaczynac tak:

org 7c00h ; lub "org 0", oczywiscie

start:
jmp short kod
nop

;==================================

db ' ' ; nazwa OS i wersja OEM (8B)
dw 512 ; bajtow/sektor (2B)
db 1 ; sektory/jednostke alokacji (1B)
dw 1 ; zarezerwowane sektory (2B)
db 2 ; liczba tablic alokacji (1B)
dw 224 ; liczba pozycji w katalogu glownym (2B),
; zwykle 224

dw 2880 ; liczba sektorow (2B)
db 0f0h ; Media Descriptor Byte (1B)
dw 9 ; sektory/FAT (2B)
dw 18 ; sektory/sciezke (2B)
dw 2 ; liczba glowic (2B)
dd 0 ; liczba ukrytych sektorow (4B)
dd 0 ; liczba sektorow (czesc 2), jesli
; wczesniej 0 (4B)

db 0 ; numer dysku (1B)
db 0 ; zarezerw. (1B)
db 0 ; rozszerzona sygnatura bloku ladujacego (1B)
dd 0bbbbddddh ; numer seryjny dysku (4B)
db ' ' ; etykieta (11B)
db 'FAT 12 ' ; typ FAT (8B), zwykle "FAT 12 "

;==================================

kod:
; tutaj dopiero kod bootsektora

======================================



Ta porcja oczywiscie uszczupla ilosc kodu, ktora mozna umiescic w
bootsektorze. Nie jest to jednak duzy problem, gdyz i tak jedyna rola
wiekszosci bootsektorow jest uruchomienie innych programow (tzw. second
stage boot-loaders), ktore dopiero zajmuja sie ladowaniem wlasciwego
systemu.



Jeszcze ciekawostka: co wypisuje BIOS, gdy dysk jest niewlasciwy
(tj. niesystemowy)?
Otoz - nic! BIOS bardzo chetnie przeszedlby do kolejnego urzadzenia.
Dlaczego wiec tego nie robi i skad ten napis o niewlasciwym dysku systemowym??
Odpowiedz jest prosta - sformatowana dyskietka posiada bootsektor!

Dla BIOSu jest wszystko OK, uruchamia wiec ten bootsektor. Dopiero ten
wypisuje informacje o niewlasciwym dysku, czeka na nacisniecie klawisza,
po czym uruchamia int 19h. O tym, co robi przerwanie 19h mozecie
przeczytac w artykule o resetowaniu.


Milego bootowania systemu!

P.S. Jesli nie chcecie przy najdrobniejszej zmianie kodu resetowac komputera,
mozecie poszukac w Internecie programow, ktore symuluja procesor (w tym
faze ladowania systemu). Jednym z takich programow jest Bochs, ktory
znajdziecie tu: http://bochs.sourceforge.net/.



Wyszukiwarka

Podobne podstrony:
DOS DIOD TUT
DOS PWR TUT
DOS MYSZ TUT
DOS GRAF TUT
DOS SPKR TUT
DOS CPU TUT
DOS SYS TUT
DOS BIBL TUT
BOOT TUT
BOOT TUT
DOS TSR TUT
DOS BMP TUT
BOOT TUT
FUNFACE DOS OPIS
Hirens Boot
CDRLab pl Hiren s Boot USB
ART121 tut 2

więcej podobnych podstron