Vaikka tämä nyt ei mitenkään coolbasiciin liity, ajattelin, että hyvin monelle aloittelevalle assembly-ohjelmoijalle (kuten minulle) voisi olla tästä tutoriaalista hyötyä.
Kyseessä on siis oman käyttöjärjestelmän koodaaminen ihan perusteista lähtien käyttäen assemblyä ja C-kieltä. Pyrin tässä oppaassa antamaan ohjeet sekä windowsille että linuxille, mutta suosittelen kuitenkin käyttämään linuxia siksi, että sillä on huomattavasti helpompi asentaa tarvittavat ohjelmat jos vain terminaali on hallussa. Netistä kyllä löytyy kohtuullisen helposti muitakin oppaita aiheesta, mutta ne ovat usein englanniksi ja käsittelevät melko vanhoja ohjelmia, joita ei vättämättä ole enää saatavilla tai toimivat eri lailla nykyään. (Hyviä esimerkkejä ovat qemu ja partcopy.exe) No niin, jaarittelu seis ja aloitetaan.
- Tarvittavat laitteet/työkalut:
- Tietokone, jossa on käyttöjärjestelmänä windows tai linux (tässä käytän ubuntua)
- Nasm-assembler. Voidaan asentaa ubuntulle kirjoittamalla terminaaliin sudo apt-get install build-essential nasm
- 3,5 tuuman tyhjä korppu ja sille asema tai:
- Mikä tahansa virtuaalikone, joka tukee boottaamista virtuaaliselta korpulta. Itse käyttäisin ubuntulla qemua, mutta jostain syystä en saanut sitä toimimaan ja sivutkin näyttävät olevan kaatuneet.
Tämä osio on kohtuullisen helppo, vaikka aikaisempaa kokemusta assembly-ohjelmoinnista ei olisikaan. Tässä koodaamme assemblyllä bootloaderin, eli 512 tavun (jep, luit oikein, se on noin lyhyt) mittaisen ohjelman, joka lataa tulevaisuudessa käyttöjärjestelmämme muun datan. Nyt kuitenkin laitamme sen vain tulostamaan klassisen tekstin Hello World, että saamme jotain boottaamaan.
Tässä vaiheessa kannattaa luoda oma kansio käyttöjärjestelmällesi. Kun olet luonut kansion haluamaasi paikkaan, tee tyhjä tiedosto nimellä boot.txt kansioosi. Avaa tiedosto ja kirjoita sinne seuraava koodi:
Code: Select all
BITS 16
org 0x7c00
Start: jmp loader
msg db "Hello, World!", 0
Print:
lodsb
or al, al
jz PrintDone
mov ah, 0eh
int 10h
jmp Print
PrintDone:
ret
loader:
xor ax, ax
mov ds, ax
mov es, ax
mov si, msg
Call Print
xor ax, ax
int 0x12
cli
hlt
times 510 - ($-$$) db 0
dw 0xAA55
BITS 16 kertoo prosessorille että tämä koodi käyttää 16-bittisiä komentoja. Kaikki bootloaderit käyttävät vain niitä.
org 0x7c00 kertoo prosessorille, mihin muistiosoitteeseen ohjelma pitää asettaa. Bootloaderit käynnistyvät aina osoitteesta 0x7c00 eivätkä mistään muualta.
Start: jmp loader hyppää (jump) seuraavat koodirivit yli loader-kohtaan.
msg db "Hello, World!" kertoo kääntäjälle, että tässä kohtaa tiedostoa on msg-niminen kohta, joka sisältää dataa. Tämä on melkein kuin muuttuja.
Print: "funktio", joka käy läpi kaikki tavut tietyssä kohtaa ja tulostaa ne näytölle.
-lodsb lataa seuraavan tavun rekisteriin. Rekisterit ovat vähän niin kuin koneen sisäisiä muuttujia, joille voidaan tehdä laskutoimituksia.
-or al, al tarkistaa, onko ladattu tavu 0, eli onko tekstiä jäljellä.
-jz PrintDone jos on, on valmis ja hypätään kohtaan PrintDone.
-mov ah, 0eh siirtää (move) luetun tavun rekisteriin ah, josta
-int 10h-ohjelmakeskeytys (interrupt) sen ottaa ja tulostaa näytölle.
-jmp Print hyppää takaisin alkuun.
-PrintDone: tässä kohtaa ollaan valmiita, joten
-ret palauttaa (return) "funktion" takaisin sinne, mistä kutsuttiin.
loader: on osio, johon hypättiin alussa.
xor ax, ax asettaa ax-rekisterin nollaksi, koska ax XOR ax on aina 0.
mov ds/es, ax siirtää ax-rekisterin arvon (0) rekistereihin ds ja es.
mov si, msg löytää lähdeindeksin "Hello, World!"-tekstille Print-kohtaa varten.
Call Print kutsuu print-kohtaa, joka tulostaa tekstin näytölle.
xor ax, ax nollaa taas ax-rekisterin.
int 0x12 on taas yksi kätevä ohjelmakeskeytys. Tämä asettaa ax-rekisterin arvoksi nykyisen työmuistin määrän kilotavuina. Tätä tarvitaan myöhemmin.
cli puhdistaa ohjelmakeskeytykset (clear interrupts)
hlt pysäyttää (halt) järjestelmän nykyiseen tilaansa. Silloin näytöllä ehtii näkyäkin jotain.
times 510 - ($-$$) db 0 täyttää bootsektorin nollilla 510 tavuun asti.
dw 0xAA55 antaa sektorille oman allekirjoituksen, että järjestelmä tunnistaa sen lopun. Näin boottisektori on tasan 512 tavua pitkä (510 + 2)
Kääntäminen:
Nyt käännämme koodimme konekieleksi nasm-assemblerilla. Nimeä ensiksi uudelleen boot.txt boot.asm-nimellä.
Windows:
Ennen tätä vaihetta tarkista, että boot.binin koko on 512 tavua. Jos se ei ole, olet tehnyt jotain väärin. Nyt siirrämme bootloaderimme korpulle, jolta voimme käynnistää sen.
Windows:
Kaikki pitäisi olla valmista. Käynnistä tietokoneesi/vrtuaalikoneesi uudelleen korppu asemassa ja varmista, että tietokoneesi käynnistysjärjestyksessä on Floppy drive ennen Hard disk driveä. Käynnistysjärjestykseen pääsee käsiksi tietokoneesta riippuen painamalla jotain funktionäppäintä tietokoneen käynnistyessä. Jos kaikki meni oikein, Tietokoneesi pitäisi käynnistyä ja kirjoittaa näytölle teksti "Hello, world!"
Onneksi olkoon, olet juuri tehnyt ensimmäisen bootloaderisi!
Ohhoh, tämähän on ensimmmäinen tutoriaalini Toivottavasti tykkäätte