BasicOS - A Minimal Operating System
Hello World!
死循環沒什麽意思,我們來嚐試輸出一句 Hello, World!
問題來了,如何在匯編中打印字符?首先,我們要設置要打印哪個字符。我們隻需要將字符存儲在 ax 寄存器的低 8 位(也就是 al 寄存器),然後調用 int 0x10 中斷執行打印即可。
對於此時的 x86 CPU 來講,一共有 4 個 16 位通用寄存器,包括 ax、bx、cx 和 dx。有時候我們隻需要使用 8 位,因此每個 16 位寄存器可以拆為兩個 8 位寄存器,例如 al 和 ah。
什麽是中斷?簡單來講就是給 CPU 正在做的事情按下暫停,然後去執行我們指定的任務。中斷可以執行的任務被存儲在內存最開始的區域,這個區域像一張表格(中斷向量表),每個單元格指向一段指令的地址,也就是 ISR(interrupt service routines)。
為了方便在匯編中調用,BIOS 給這些中斷分配了號碼。例如,int 0x10 就是第 16 個中斷,它指向了一個打印字符的 ISR。
然而 int 0x10 中斷隻知道要打印,但並不知道要怎麽打印。我們這裏將其設置為 TTY(TeleTYpe)模式,讓它接收字符並顯示在屏幕上,然後將光標向後移動。設置 TTY 模式的方法是將 ah 寄存器設置為 0x0e,你可以理解為傳給係統中斷的參數。
why have to load into 0x7c00?
512 字節小小的也很可愛,但顯然滿足不了操作係統龐大的欲望,因此操作係統的絕大部分代碼被放在磁盤的其它地方。這些代碼是如何加載到內存的呢?
在回答如何加載到內存之前,我們先關注另一個更緊迫的問題:加載時應該加載到內存的哪裏?
答案是,引導扇區並沒有被加載到內存的 0x0000 處。這是因為內存中還需要存儲一些重要的信息,例如中斷向量表、BIOS 數據區等。這些內容需要占用一部分內存,因此有人規定,引導扇區應當被加載到 0x7c00 處。
更具體地講,開頭這塊的內存布局如下:
0x100000 +-----------------------+
| BIOS (256 KB) |
0x0C0000 +-----------------------+
| Video Memory (128 KB) |
0x0A0000 +-----------------------+
|Extended BIOS Data Area|
| (639 KB) |
0x09FC00 +-----------------------+
| Free (638 KB) |
0x007E00 +-----------------------+
| Loaded Boot Sector |
| (512 Bytes) |
0x007C00 +-----------------------+
| |
0x000500 +-----------------------+
| BIOS Data Area |
| (256 Bytes) |
0x000400 +-----------------------+
| Interrupt Vector Table|
| (1 KB) |
0x000000 +-----------------------+
編譯
創建磁盤映像
創建一個 1.44MB 的空磁盤映像:
將引導扇區寫入磁盤映像:
測試引導扇區
你應該能看到屏幕打印出 Hello, world!,然後程序進入死循環。