Jak przygotować się do developmentu systemów operacyjnych

Prawdopodobnie jesteś tutaj aby nauczyć się jak zacząć przygodę z OSDEVem. To jest szybki poradnik aby zacząć wyświetlać tekst na swoim własnym ekranie. Zaczniemy tutaj z pisaniem prostego assemblera, który normalnie jest uznawany jako bootloader. Polecam zainstalowanie jakiegoś IDE takiego jak Visual Studio Code lub innych. W tym przypadku użyjemy VS Code.

Do tego poradnika narazie potrzebujemy dwóch programów:

nasm – Potrzebny do kompilowania kodu

qemu – Potrzebny do uruchamiania systemu

Teraz pokaże kod który pisze Hello, World! na ekranie –


bits 16
org 0x7c00

global start
start:
    push cs
    pop ds
    mov si, msg
print:
   lodsb
   test al, al
   jz .done
   mov ah, 0x0e
   int 0x10
   jmp print
.done:
    hlt
    jmp .done

msg: db "Hello, World!", 0
times 510-($-$$) db 0
dw 0xAA55

To może być skomplikowane, więc wyjaśnie wszystkie linie tutaj:

bits 16 – Potrzebny, aby kompilator wiedział że jesteśmy w trybie 16-bitowym

org 0x7c00 – Ta linia jest bardzo ważna, bo linker zazwyczaj ustawia nasz kod na adresie 0x0, więc nadpisujemy BIOS, i wtedy nie ma co odpalić, bo nie ma czym.

global start – Ta linia powoduje że BIOS wie gdzie znajduje się punkt wejściowy dla systemu

start – Definicja “funkcji”

push cs – Jest taka rzecz jak stack, która ma jakieś dane, i używa tzw. stack pointera (sp), i kiedy my wykonujemy push (coś) to wartość tego coś jest wrzucona na adres na który wskazuje stack pointer, i obniża wartość sp o 4.

pop ds – Pop (coś) to jest to samo jak z push (coś), tylko na odwrót. Pop (coś) zyskuje dane z sp i wartość tych danych znajduje się w tym czymś.

mov si, msg – Instrukcja mov powoduje, że wartość pierwszej rzeczy podanej, jest równa drugiej rzeczy, czyli w tym przypadku SI ma wartość “Hello, World!”.

print – Definicja “funkcji” która służy za pokazywanie liter na ekran

lodsb – Ta instrukcja jest trochę skomplikowana, ale bardzo przydatna. Działa mniej więcej tak:

 mov al, [si] inc si 

Czyli: bierze bajt spod adresu wskazywanego przez rejestr SI, zapisuje go do AL, a potem zwiększa SI, żeby wskazywał na następny znak w pamięci.

test al, al – Ta instrukcja sprawdza, czy rejestr AL ma wartość 0. Nie zmienia jego wartości, tylko ustawia flagi procesora.

jz .done – Jeśli wynik testu był równy zero (czyli trafiliśmy na znak 0 kończący string), skaczemy do etykiety .done.

mov ah, 0x0e – Ustawiamy funkcję BIOS-u. 0x0E to tryb „teletype output”, który wypisuje znak na ekranie i automatycznie przesuwa kursor.

int 0x10 – Wywołanie przerwania BIOS-u odpowiedzialnego za obsługę ekranu. BIOS bierze znak z rejestru AL i wypisuje go.

jmp print – Skaczemy z powrotem do etykiety print, aby wypisać kolejny znak.

.done: – Etykieta kończąca pętlę wypisywania tekstu.

hlt – Instrukcja zatrzymująca procesor do momentu następnego przerwania. Ponieważ nie mamy jeszcze systemu operacyjnego, po prostu „zamrażamy” CPU.

jmp .done – Prosta pętla nieskończona. Gdyby procesor się obudził, wróci z powrotem do hlt.

msg: db “Hello, World!”, 0 – Definicja danych. Tworzymy w pamięci tekst zakończony bajtem 0, który informuje nasz kod, gdzie kończy się napis.

times 510-($-$$) db 0 – Dopełniamy sektor zerami tak, aby cały bootloader miał dokładnie 512 bajtów.

dw 0xAA55 – Sygnatura bootloadera. BIOS sprawdza te dwa bajty, aby upewnić się, że sektor jest bootowalny. Bez tego kod się nie uruchomi.

Po skompilowaniu tego kodu i uruchomieniu go w QEMU zobaczysz na ekranie klasyczne Hello, World!. To jest pierwszy krok w OSDEV-ie – od tego momentu masz pełną kontrolę nad maszyną.

Aby skompilować ten kod, można użyć instrukcji: nasm -f bin plik.asm -o os.bin, gdzie plik.asm to jest wasz plik który stworzyliście i gdzie macie kod. Po tym wystarczy uruchomić: qemu-system-i386 -drive format=raw,file=os.bin, i gotowe! Jeżeli qemu się zamknie od razu, to prawdopodobnie zapomnieliście sygnatury bootloadera.

I to jest koniec na ten poradnik. W następnym poradniku pokażę jak zainstalować cross compiler, i pokazać coś więcej na ekranie.

Leave a Reply

Your email address will not be published. Required fields are marked *