Forum dyskusyjne  |  Kanał IRC | Użytkownicy | Hosting
Boot loader cz. 1.
2006-08-05 18:15:41, wyświetleń: 10392 [ edycja ] | [ historia ]


Pierwsze kroki

Jak na razie dla wygody nasz system będziemy umieszczać na dyskietce. W końcu jak na razie pewnie nikt nie chce sobie zepsuć boot sektora, który jest na dysku twardym :P. A na początku póki nie opisze systemu plików (o tym będzie osobny art), zepsujemy cały system plików, który jest na dyskietce, albo inaczej "stworzymy własny system plików" - tak ładniej brzmi :]
Zanim zaczniemy pisać nasz pierwszy system operacyjny, musimy napisać boot loadera, który nam to jądro załaduje. No to zaczynamy:

Co to w ogóle jest boot loader?

Boot loader jest to mały program który ma za zadanie załadować i uruchomić system operacyjny.
Bios ładuje do ramu tak zwany boot sektor (inaczej MBR - Master Boot Record), czyli pierwszy sektor pod zerową głowicą i na zerowej ścieżce pierwszego ustawionego urządzenia bootującego, pod warunkiem, że znajduje się tam boot loader. Boot loader musi zajmować dokładnie 512 bajtów (czyli tyle ile jeden segment w trybie rzeczywistym) a dwa ostatnie bajty musza mieć wartość AA55h. Jeżeli nie ustawimy takiej ostatniej wartości to Bios uzna, że nie ma boot loadera. Jeżeli jednak wszystko pójdzie dobrze to w pamięci pod adresem 0000:7C00H będzie boot loader. Gdy bios oddaje kontrolę boot loaderowi wszystkie rejestry segmentowe są wyzerowane, a DL zawiera numer dysku, z którego pochodzi boot sektor (0 to dyskietka, 80h - pierwszy dysk twardy).

A oto przykład najprostszego boot loadera:
Boot.asm:

Kod:
aa:                            ;wykonujemy nieskończoną pętle         
jmp aa                       ;aby nie wywołać błędu.
times 510-($-$$) db 0  ;zapełniamy plik do końca, aby miał 510bajtow
dw 0AA55h                ;No i na końcu dodajemy wartość 0AA55h


A teraz kompilujemy:

nasm boot.asm -o boot.bin

Teraz programem RawWrite kopiujemy nasz plik boot.bin na dyskietkę(traktujemy go jako obraz). No i uruchamiamy emulator i widzimy czarny ekran :] Czyli wszystko się udało, nasz pierwszy boot loader został załadowany bez żadnych błędów.

Wcześniej wspomniałem o "własnym formacie plików", jest on bardzo prosty - w pierwszy sektorze będzie znajdował się boot loader a zaraz w drugim początek naszego kernela. Czyli teraz rozbudujemy boot loadera o to ze będzie wczytywał do pamięci drugi sektor i przekazywał mu kontrole. Do czytania użyjemy przerwania biosu 13h.

Kod na wczytanie drugiego sektora z dyskietki pod adres 0800h:

Kod:
mov ah, 2         ;funkcja 2 przerwania 13h
mov al, 10        ;ilość sektorów do przeczytania (10*512 = 5kb)
mov ch, 0         ;cylinder
mov cl, 2          ;sektor (w 1 jest bootsector)
mov dh, 0         ;głowica
mov bx, 0800h  ;gdzie załadować kernel (es:bx)
mov es, bx       ;dane do ES możemy umieścić tylko przez inny rejestr
xor bx, bx        ;bx równy 0
int 13h             ;wywołujemy przerwanie


Aby teraz boot loader uruchomił to, co załadował do pamięci (czyli coś, co nazywamy kernelem) musimy wykonać skok do tego miejsca, czyli krótko i na temat:

Kod:
jmp 0800h:0000h


I to już cały boot loader. A oto cały kod:

Kod:
org 7C00h

start:
  mov ah, 2
  mov al, 10
  mov ch, 0
  mov cl, 2
  mov dh, 0
  mov bx, 0800h
  mov es, bx
  xor bx, bx
  int 13h

  jmp 0800h:0000h

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


Aby sprawdzić czy nasz boot loader działa musimy jeszcze napisać jakiegoś przykładowego kernela. A oto on:

Kernel.asm:

Kod:
mov ah, 9
mov al, '='
mov bx, 7
mov cx, 10
int 10h
hang:
jmp hang


Dobra, mamy boot loader i kernela, pozostaje tylko jedno pytanie jak skopiować na dyskietkę boot loadera do pierwszego sektora a kernela do drugiego?
Teraz napiszemy sobie w delphi prosty program, który połączy nam te dwa pliki w jeden (krótko mówiąc zrobimy sobie obraz dyskietki). Cały czas kompilujemy z linii poleceń, więc dla wygody napiszemy sobie tez taki programik, nie będziemy się tu bawić komponentami VCL, bo w tym przypadku to strata czasu.

Kod:
program zlacz;

{$APPTYPE CONSOLE}

var
  final, f: file of byte;
  buf, q: byte;
begin
  if (paramcount < 3) then
   writeln('uzycie: zlacz    ')
   else begin
    assignfile(final, paramstr(paramcount));
    rewrite(final);
    for q := 1 to paramcount -1 do begin
      writeln(paramstr(q));
      assignfile(f, paramstr(q));
      reset(f);
      while not eof(f) do begin
        blockread(f, buf, sizeof(buf));
        blockwrite(final, buf, sizeof(buf));
      end;
      closefile(f);
    end;
    closefile(final);
    writeln('Gotowe!!!');
  end;
end.


A teraz kompilujemy całość:

nasm boot.asm -o boot.bin
nasm kernel.asm -o kernel.bin
zlacz boot.bin kernel.bin image.img


I teraz RawWritem nagrywamy plik image.img. Odpalamy emulator i widzimy naszego pierwszego kernela :]

Autor: Michał Ślaga (Destruction)
gg: 4029168



Autor: Destruction

Komentarze
Artykuły mogą być komentowane wyłącznie przez zarejestrowanych użytkowników.

Zaloguj się | Załóż nowe konto

2010-02-05 15:10:56

jak najszybciej
l4C
2010-02-05 14:50:41

mam pytanie, jak zrobić bootloader nie pod Dyskietke tylko pod CD?
2008-07-12 18:23:40

Delphi, albo free pascal też powinien dać radę z dyrektywą {$MODE DELPHI}
2008-07-12 17:10:11

Ej, czym skompilować ten program program "zlacz"?
mrX
2008-07-09 01:03:20

W Linuksie bardzo łatwo załatwia się poleceniem dd.
2008-07-02 20:33:57

Nie musisz korzystac z rawwrite"a, w ogole nie musisz korzystac z zadnego programu do tego z netu, napisz sobie sam program po prostu przepisujacy to do obrazu dyskietki, jak chcesz to Ci swoj podesle jakis tam napisalem jak sie tez bawilem w osy.
2008-07-02 17:32:28

a ja mam problem z RawWritem , podaje lokacje pliku Boot.bin ;enter,wciskam A ; enter ;enter , program sie zamyka , wchodze w dyskietke a tam niczego nie ma
mrX
2008-04-04 16:40:54

Bardzo fajnie, czekam na kolejną część
Redakcja zastrzega sobie prawo do skracania, usuwania komentarzy o treściach wulgarnych, obraźliwych oraz niezgodnych z polskim i miedzynarodowym prawem. Unit1.pl Team nie ponosi odpowiedzialności za treść komentarza.