adres = segment * 16 + offsetW sumie 20 bitów (max 1MB pamięci)
; Adres startowy 0000:7c00 [ORG 0x07c00] [BITS 16] mov ax, 0xb800 ; ustawiamy segment es na początek mov es,ax ; pamięci karty video mov byte [es:0],0x41 ; wpisujemy znak A w górny lewy róg mov byte [es:1],0x1f ; ustawiamy atrybuty (kolor i tło) loop1: jmp loop1 ; zapętlamy times 510 - ($-$$) db 0 ; uzupełniamy zerami do pozycji 510 dw 0x0aa55 ; wartość aa55 oznacza, ;że jest to sektor bootowalny
Kompilujemy poleceniem
nasm boot1.asm -fbin -o boot1.bin
Tak przygotowany bootsector możemy przekopiować do pierwszego sektora dysku, pendrive czy innego nośnika np. poleceniem
dd if=./boot1.bin of=/dev/sdb1 bs=512 count=1
Można też tak przygotowany plik uruchomić bezpośrednio w emulatorze np.
qemu -hda ./boot1.bin
BIOS (Basic Input/Output System) to zapisany w pamięci stałej
zestaw podstawowych procedur zapewniających podstawową komunikację z
urządzeniami zewnętrznymi tj. ekran, klawiatura, dyski.
Komunikacja z BIOS-em odbywa się przez przerwania.
Lista przerwań BIOS-a.
Lista dostępnych przerwań zależy od płyty głównej oraz od
wersji BIOS-u wgranej do pamięci EPROM.
Przerwanie 0x10 w głównej mierze jest odpowiedzialne za wyjście na ekran i obsługę klawiatury. Numer wybranej funkcji umieszczamy w rejestrze AH
[ORG 0x07c00] [BITS 16] mov ax, 0 mov es, ax ; ustawienie segmentu ES na zero mov ah, 0x03 ; pobranie aktualnej pozycji kursora mov bh, 0 ; strona 0 int 0x10 ; wynik będzie w dh (wiersz) dl (kolumna) mov ah, 0x13 ; wypisanie tekstu mov al, 0x01 ; tryb pisania : bit 0 - przesunąc kursor po zapisie ; bit 1 - tekst zawiera na przemian litery i atrybuty znaków mov cx, msglen ; długość tekstu mov bh, 0x00 ; strona ekranu mov bl, 0x07 ; atrybuty znaków (biały na czarnym tle) mov bp, msg ; wskaźnik na tekst ES:BP ; mov dx, 0x0000 ; gdzie wypisać (górny lewy róg) int 0x10 loop1: hlt ; zatrzymujemy procesor jmp loop1 ; zapętlamy msg: db "Pozdrowienia z bootloadera! ", 13, 10, 0 msglen equ ($-msg-1) times 510 - ($-$$) db 0 ; uzupełniamy zerami do pozycji 510 dw 0x0aa55 ; wartość aa55 oznacza, ;że jest to sektor bootowalny
Przerwanie 0x13 zapewnia dostęp do dysku.
Możemy wczytywać dany sektor dysku podająć kolejno numer cylindra, głowicy i sektoru. Ten tryb adresowania oznacza się przez CHS (Cylinder-Head-Sector). Jednakże wygodniej jest stosować tryb LBA (Logical block addressing) który każdemu sektorowi nadaje logiczny adres, który potem jest przeliczany na adres CHS wedlug wzoru
LBA = ( numer_cylindra * liczba_glowic_na_cylinder + numer_glowicy ) * liczba_sektorow_na_sciezke + numer_sektora -1
mov ax, 0 mov ds, ax ; ustawienie segmentu DS na zero mov ah, 0x42 ; odczyt LBA mov dl, 0x80 ; numer dysku (dysk nr 0) mov si, read_pocket ; DS:SI adres struktury definiujacej ile przeczytać i gdzie umieścić int 0x13 ;... read_pocket: db 0x10 ; rozmiar rekordu (pocket) db 0 ; zarezerwowane = 0 dw 1 ; ile sektorów odczytać dd 0x00007E00 ; gdzie umieścić wynik dd 1 ; który sektor odczytać dd 0 ; starsze bajty nr. sektora
Przykład: Bootloader wczytuje drugi sektor dysku i wykorzystuje zawarte w nim informacje.