System operacyjny
Inicjalizacja systemu
Tryb rzeczywisty
Większość procesorów z serii 80x86 w stanie początkowym pracuje w 16 bitowym trybie rzeczywistym:
Bootsector

; 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
Jest to format wyjściowy, w którym nie ma żadnych nagłówków a kod źródłowy w całości bezpośrednio zamieniany na kod maszynowy.

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

Przerwania BIOS-a

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

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

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
 

Bootloader I

Przykład: Bootloader wczytuje drugi sektor dysku i wykorzystuje zawarte w nim informacje.

Kod asemblerowy

Tryb chroniony

Tryb chroniony

GDT - global descriptor table

GDT

Linia A20

A20

Przejście w tryb chroniony

Przejście w tryb chroniony

Tryb chroniony

Tomasz Kapela, Kraków 2011-2020