BOOT TUT




Pisanie bootsektorów










Pisanie boot-sektorów


Gdy już choć średnio znacie assemblera, to po pewnym czasie pojawiają się pytania
(mogą one być spowodowane
tym, co usłyszeliście na grupach dyskusyjnych lub Waszą własną ciekawością):

Co się dzieje, gdy ma zostać uruchomiony jest system operacyjny?
Skąd BIOS ma wiedzieć, którą część systemu uruchomić?
Jak BIOS odróżnia systemy operacyjne, aby móc je uruchomić?

Odpowiedź na pytanie 2 brzmi: nie wie. Odpowiedź na pytanie 3 brzmi: wcale. Wszystkie Wasze
wątpliwości rozwieje odpowiedź na pytanie 1.


Gdy zakończył się POST (Power-On Self Test), wykrywanie dysków i innych urządzeń, BIOS
przystępuje do czytania pierwszych sektorów tych urządzeń, na których ma być szukany system
operacyjny (u mnie jest ustawiona kolejność: CD-ROM, stacja dyskietek, dysk twardy).
Gdy znajdzie sektor odpowiednio zaznaczony: bajt nr 510 = 55h i bajt 511 = AAh
(pamiętajmy, że 1 sektor ma 512 bajtów, a liczymy od zera), to wczytuje go pod adres
bezwzględny 07C00h i uruchamia kod w nim zawarty (po prostu wykonuje JMP). Nie należy
jednak polegać na tym, że CS = 0 i IP=7C00h (choć najczęściej tak jest).

To właśnie
boot-sektor jest odpowiedzialny za ładowanie odpowiednich części właściwego systemu
operacyjnego. Na komputerach z wieloma systemami operacyjnymi sprawa też nie jest tak
bardzo skomplikowana. Pierwszy sektor dysku twardego, zwany Master Boot Record (MBR),
uruchamia program ładujący (tzw. Boot Manager, jak LILO czy GRUB), który z kolei
uruchamia boot-sektor wybranego systemu operacyjnego.


My oczywiście nie będziemy operować na dyskach twardych, gdyż byłoby to niebezpieczne. Z
dyskietkami zaś można ekperymentować do woli...
A instrukcja jest
prosta: umieszczamy nasz programik w pierwszym sektorze dyskietki, zaznaczamy go
odpowiednimi ostatnimi bajtami i tyle. No właśnie... niby proste, ale jak o tym pomyśleć
to ani to pierwsze, ani to drugie nie jest sprawą banalną.


Do zapisania naszego bootsektorka na dyskietkę możemy oczywiście użyć "gotowców" - programów
typu rawwrite itp. Ma to pewne zalety - program był już używany przez dużą liczbę osób, jest
sprawdzony i działa.
Ale coś by było nie tak, gdybym w kursie programowania w assemblerze kazał Wam używać
cudzych programów. Do napisania sowjego własnego programu zapisującego dany plik w pierwszy
sektor dyskietki w zupełności wystarczy Wam wiedza uzyskana po przeczytaniu części mojego
kursu poświęconej operacjom na plikach wraz z tym (wyciąg oczywiście ze

Spisu Przerwań 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 widać, sprawa już staje się prosta. Oczywiście, AL=1 (bo zapisujemy 1 sektor), DX=0 (bo
stacja ma 2 głowice, a pierwsza ma numer 0, zaś numer dysku 0 wskazuje stację A:), CX=1 (bo
numery sektorów zaczynają się od 1, a zapisujemy w pierwszym cylindrze i ma on numer 0).
Tak więc, schemat jest taki:

Otwórz plik
Przeczytaj z niego 512 bajtów do pamięci
Zapisz je na dyskietce
Zamknij plik

Sprawa jest tak prosta, że tym razem nie podam "gotowca".


Gdy już mamy program zapisujący bootsektor na dyskietkę, trzeba się postarać o to, aby
nasz programik (który ma stać się tym bootsektorem) miał dokładnie 512 bajtów i aby 2 ostatnie
jego bajty to 55h, AAh.
Oczywiście, nie będziemy ręcznie dokładać tylu bajtów, ile trzeba, aby dopełnić nasz program
do tych 512. Zrobi to za nas kompilator. Wystarczy po całym kodzie i wszystkich danych, na
szarym końcu, umieścić takie coś (NASM/FASM):

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

Dla TASMa powinno to wyglądać mniej więcej tak:

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

To wyrażenie mówi tyle: od bieżącej pozycji w kodzie odejmij pozycję początku kodu (tym
samym obliczając długość całego kodu), otrzymaną liczbę odejmij od 510 - i dołóż tyle
właśnie bajtów zerowych. Gdy już mamy program długości 510 bajtów, to dokładamy jeszcze
znacznik i wszystko jest dobrze.


Jest jednak jeszcze jedna sprawa, o której nie wspomniałem - ustawienie DS i wartości "org"
dla naszego kodu. Otóż, jeśli stwierdzimy, że nasz kod powinien zaczynać się od offsetu
0 w naszym segmencie, to ustawmy sobie "org 0" i DS=07C0h (tak, ilość zer się zgadza), ale
możemy też mieć "org 7C00h" i DS=0. Żadne z tych nie wpływa w żaden sposób na długość
otrzymanego programu, a należy o to zadbać, gdyż nie mamy gwarancji, że DS będzie pokazywał
na nasze dane po uruchomieniu bootsektora.


Teraz, uzbrojeni w niezbędną wiedzę, zasiadamy do pisania kodu naszego bootsektora. Nie
musi to być coś wielkiego - tutaj pokażę coś, co w lewym górnym rogu ekranu pokaże cyfrę "1"
(o bezpośredniej manipulacji ekranem możecie przeczytać w moim innym artykule) i po naciśnięciu
dowolnego klawisza zresetuje komputer (na jeden ze sposobów 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 pamięci 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 gorący reset
jmp 0ffffh:0000h ; reset

times 510 - ($ - start) db 0 ; dopełnienie do 510 bajtów
dw 0aa55h ; znacznik

Nie było to długie ani trudne, prawda? Rzecz jasna, nie można w bootsektorach używać żadnych
przerwań systemowych, np. DOSowego int 21h, bo żaden system po prostu nie jest uruchomiony
i załadowany.
Tak napisany programik kompilujemy do formatu binarnego. W TASMie wyglądałoby to jakoś 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 użyciu programu napisanego już przez nas
wcześniej. Resetujemy komputer (i upewniamy się, że BIOS spróbuje uruchomić system z
dyskietki), wkładamy dyskietkę i.... cieszymy się swoim dziełem (co prawda ta jedynka
będzie mało widoczna, ale rzeczywiście znajduje się na ekranie).


Zauważcie też, że ani DOS ani Windows nie rozpoznaje już naszej dyskietki, mimo iż przedtem była
sformatowana. Dzieje się tak dlatego, że w bootsektorze umieszczane są informacje o dysku.
"Prawidłowy" DOSowy/Windowsowy bootsektor powinien się zaczynać tak:

org 7c00h ; lub "org 0", oczywiście

start:
jmp short kod
nop

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

db ' ' ; nazwa OS i wersja OEM (8B)
dw 512 ; bajtów/sektor (2B)
db 1 ; sektory/jednostkę alokacji (1B)
dw 1 ; zarezerwowane sektory (2B)
db 2 ; liczba tablic alokacji (1B)
dw 224 ; liczba pozycji w katalogu głównym (2B), zwykle 224
dw 2880 ; liczba sektorów (2B)
db 0f0h ; Media Descriptor Byte (1B)
dw 9 ; sektory/FAT (2B)
dw 18 ; sektory/ścieżkę (2B)
dw 2 ; liczba głowic (2B)
dd 0 ; liczba ukrytych sektorów (4B)
dd 0 ; liczba sektorów (część 2), jeśli wcześniej 0 (4B)
db 0 ; numer dysku (1B)
db 0 ; zarezerw. (1B)
db 0 ; rozszerzona sygnatura bloku ładującego (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 oczywiście uszczupla ilość kodu, którą można umieścić w bootsektorze. Nie jest to
jednak duży problem, gdyż i tak jedyną rolą większości bootsektorów jest uruchomienie
innych programów (tzw. second stage boot-loaders), które dopiero zajmują się ładowaniem
właściwego systemu.

Jeszcze ciekawostka: co wypisuje BIOS, gdy dysk jest niewłaściwy (tj. niesystemowy)?
Otóż - nic! BIOS bardzo chętnie przeszedłby do kolejnego urządzenia.
Dlaczego więc tego nie robi i skąd ten napis o niewłaściwym dysku systemowym??
Odpowiedź jest prosta - sformatowana dyskietka posiada bootsektor!
Dla BIOSu jest wszystko OK, uruchamia więc ten bootsektor. Dopiero ten wypisuje informację
o niewłaściwym dysku, czeka na naciśnięcie klawisza, po czym uruchamia int 19h. O tym, co
robi przerwanie 19h możecie przeczytać w artykule o resetowaniu.

Miłego bootowania systemu!

P.S. Jeśli nie chcecie przy najdrobniejszej zmianie kodu resetować komputera, możecie poszukać
w Internecie programów, które symulują procesor (w tym fazę ładowania systemu).
Jednym z takich programów jest Bochs, który znajdziecie tu:
http://bochs.sourceforge.net/.



Wyszukiwarka

Podobne podstrony:
DOS BOOT TUT
BOOT TUT
BOOT TUT
Hirens Boot
CDRLab pl Hiren s Boot USB
ART121 tut 2
phys tut 08
phys tut 12
remote boot 3 atgrgfg4ak5imci6eqdc4jtbdubmqdnh3wdeb5q atgrgfg4ak5imci6eqdc4jtbdubmqdnh3wdeb5q
DOS DIOD TUT
advanced ntfs boot and mft repair
moto boot menu
SYS TUT
ART121 tut 3
MYSZ TUT
PWR TUT
BOOT

więcej podobnych podstron