1.BIOS
-
- 0xFFFF0 電源正常啟動後,x86 CPU 會先執行 0xFFFF0,也就是 BIOS ROM 的進入點。由於 0xFFFF0 ~ 0xFFFFF 只有少的很可憐的 16 bytes,真正的 BIOS code 勢必要擺到其他位置,此時 0xFFFF0 的作用便是 jmp 到該位置執行 BIOS 程式。
- POST (Power-On Self Test) BIOS 程式的第一個動作就是執行最基本的 POST 檢查,確保系統在開機當中可以正常運作。通常用 beep 聲來表示檢查結果。各家 BIOS 的 beep 聲都不一樣,以常見的 Award BIOS 為例:
Beep | Error Message |
---|---|
1 short | POST OK! |
1 long | Memory problem |
1 long, 2 short | Video card error |
1 long, 3 short | No video card or bad video RAM |
Repeating beeps | Memory error |
High Frequency beeps | Overheating CPU |
-
- Video Card BIOS POST 之後的首要任務就是啟動顯示卡,畢竟沒有螢幕是很痛苦的一件事情。顯示卡有自己的 BIOS,這時系統 BIOS 會掃描記憶體 0xC000:0000 ~ 0xC780:0000,也就是顯示卡 BIOS 位址,並 jmp 過去執行顯示卡的初始化。一旦成功,開機後的第一個畫面就出現了。
-
- 除了顯示卡,其他有自己 BIOS 的裝置也都在這時候啟動,例如 IDE/ATA BIOS 位於 0xC8000。
- Full POST 有了螢幕之後再來一次總檢查:
- Video Test: 初始化顯示卡插槽並測試顯示卡和顯示記憶體。
- BIOS Identification: 顯示 BIOS 版本、製造商及日期。
- Memory Test: 測試並顯示安裝的主記憶體總容量數。
-
- 除了上述檢查之外,BIOS 還會讀取存 CMOS configuration 資料。這些放在靠小電池維生的 64 bytes CMOS 當中的資料,紀錄著一些使用者可調變的系統資訊,也就是開機時按 Del 鍵進去調整的那堆東西。另外也會做一些額外的檢查,例如動態設定 IDE/ATA 裝置的參數等等,同時顯示在這個畫面當中。
- Summary Screen 一切就緒之後,就像寫論說文「起、承、轉、合」一樣,要來「合」一下。這時 BIOS 會將整個系統資訊都顯示在螢幕上,表示開機動作大抵完成,接下來就準備交棒給下一個程式了。
-
- Booting BIOS 所執行的最後一個動作就是交接,將執行權交給下一支程式,boot loader 也好,OS 也好,或者單純的一支小程式。這時會依設定的順序搜尋各開機磁碟裝置 (floppy disk, hard disk, CD-ROM, ...) 的 cylinder 0, head 0, sector 1 (對 hard disk 來說就是 Master Boot Record, MBR),並將該 512 bytes 載入至記憶體 0x0000:7C00 而 jmp 過去完成交接 (注意此時 CS:IP 為 0x0000:7C00 而不是 0x07C0:0000)。對於 MBR 而言,還要多檢查最後兩 bytes 為 0x55AA,才判定為有效的 MBR 並 jmp 過去完成交接;否則繼續搜尋下一個裝置,直到沒有裝置則顯示 "No boot device available" 之類的錯誤訊息。
-
- Hello World
- INT 0x10, INT 0x16 利用 BIOS 內建的 INT 0x10,我們可以輕易將字元印在螢幕上;INT 0x16 則可讀取鍵盤的輸入。以下為簡易的 NASM Code,在螢幕中央印出 "Hello Jasonmel!" 之後讀取字元,每讀一個字元之後將它以藍底黃字顯示在螢幕上,除了 Ctrl+C 會重新開始。
[BITS 16] ORG 0 jmp START START: ; code located at 0x0000:7C00, adjust segment registers cli mov ax, 0x07C0 mov ds, ax mov es, ax mov fs, ax mov gs, ax ; create stack mov ax, 0x0000 mov ss, ax mov sp, 0xFFFF sti ; set_VGA_mode mov ah, 0x00 ; set display mode mov al, 0x02 ; 640x200, 16 color, 80x25, 8 pages int 0x10 ; invoke BIOS ; set_cursor mov ah, 0x02 ; set cursor mov dh, 0x0C ; row number (12d) mov dl, 0x1E ; col number (31d) mov bh, 0x00 ; page number int 0x10 ; invoke BIOS ; post message mov si, msgHello call DisplayMessage ; set_cursor mov ah, 0x02 ; set cursor mov dh, 0x0D ; row number (13d) mov dl, 0x25 ; col number (37d) mov bh, 0x00 ; page number int 0x10 ; invoke BIOS GetChar: mov ah, 0x00 ; get keyboard char int 0x16 cmp al, 0x03 ; if "Ctrl+C" je END ; yes? goto end; ; print mov ah, 0x09 ; print mov bh, 0x00 ; page number mov bl, 0x1E ; property 'yellow word, blue background' mov cx, 0x01 ; times int 0x10 ; invoke BIOS jmp GetChar ; goto GetChar; END: int 0x19 ; jump to FFFF:0 (BIOS) int 0x20 ; end DisplayMessage: lodsb ; load next character or al, al ; test for NUL character jz .DONE mov ah, 0x0E ; BIOS teletype mov bh, 0x00 ; display page 0 mov bl, 0x07 ; text attribute int 0x10 ; invoke BIOS jmp DisplayMessage .DONE: ret msgHello db "Hello Jasonmel!", 0x0D, 0x0A, 0x00 TIMES 510-($-$$) DB 0 DW 0xAA55
-
- 執行畫面如下,按下 Ctrl+A 會顯示下面的笑臉。
-
- Boot Loader
- Booting A Program 非常簡單!利用 BIOS INT 0x13 載入該 sector 至記憶體並且 jmp 過去即可。這時要注意避免使用一些已使用的記憶體區段,陳列如下 (部分參考自
-
- ):
0x0000:0 Interrupt Vector Table 0x0040:0 BIOS Data Area 0x0050:0 PrtScr Status / Unused 0x0060:0 Image Load Address 0x07C0:0 Boot code is loaded here at startup (31k mark) 0xA000:0 EGA/VGA RAM for graphics display mode 0Dh & above 0xB000:0 MDA RAM, Hercules graphics display RAM 0xB800:0 CGA display RAM 0xC000:0 EGA/VGA BIOS ROM (thru C7FF) 0xC400:0 Video adapter ROM space 0xC600:0 256 B PGA communication area 0xC800:0 16 KB Hard disk adapter BIOS ROM 0xC800:5 XT Hard disk ROM format, AH=Drive, AL=Interleave 0xD000:0 32 KB Cluster adapter BIOS ROM 0xD800:0 PCjr conventionalsoftware cartridge address 0xE000:0 64 KB Expansion ROM space (hardwired on AT+) 128 KB PS/2 System ROM (thru F000) 0xF000:0 System monitor ROM PCjr: software cartridge override address 0xF400:0 System expansion ROMs 0xF600:0 IBM ROM BASIC (AT) 0xF800:0 PCjr software cartridge override address 0xFC00:0 BIOS ROM 0xFF00:0 System ROM 0xFFA6:E ROM graphics character table 0xFFFF:0 ROM bootstrap code 0xFFFF:5 8 B ROM date (not applicable for all clones) 0xFFFF:E 1 B ROM machine id
-
- 其中比較關鍵的 assembly code 如下。由於讀取可能發生錯誤,因此一般會多加錯誤判斷並多讀幾次比較保險。
-
- Master Boot Record (MBR) MBR 位於 hard disk 的 cylinder 0, head 0, sector 1,紀錄著 hard disk 的分割狀態,於開機時被載入至記憶體 0x0000:7C00。開始執行後,由程式依序搜尋 partition 並 check 是否為 active (80),若是,則將控制權繼續交給 active partition。為了避免覆蓋,通常 MBR 會事先將自己搬到 0x0000:0600 的位置,之後才將 partition 的 boot sector 載入至記憶體 0x0000:7C00,再 jmp 過去完成交接。
-
- MBR 格式如下:
+--------+----------------------------------------------------+ | OFFSET | 0 1 2 3 4 5 6 7 8 9 A B C D E F | +--------+----------------------------------------------------+ | 0x0000 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x0010 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x0020 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x0030 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x0040 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x0050 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x0060 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0x0070 - 0x015F 也都是 CC 故省略 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 0x0160 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x0170 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x0180 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x0190 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x01a0 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC | | 0x01b0 | CC CC CC CC CC CC CC CC CC CC CC CC CC CC P1 P1 | | 0x01c0 | P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P1 P2 P2 | | 0x01d0 | P2 P2 P2 P2 P2 P2 P2 P2 P2 P2 P2 P2 P2 P2 P3 P3 | | 0x01e0 | P3 P3 P3 P3 P3 P3 P3 P3 P3 P3 P3 P3 P3 P3 P4 P4 | | 0x01f0 | P4 P4 P4 P4 P4 P4 P4 P4 P4 P4 P4 P4 P4 P4 55 AA | +--------+----------------------------------------------------+ CC: 0x0000 to 0x01BD - Boot loader code (First 446 bytes) P1: 0x01BE to 0x01CD - Partition entry 1 P2: 0x01CE to 0x01DD - Partition entry 2 P3: 0x01DE to 0x01ED - Partition entry 3 P4: 0x01EE to 0x01FD - Partition entry 4 55AA: 0x01FE to 0x01FF - Boot signature
-
- 其中 Partition Entry 格式如下:
+------------+----+-----------+----+-----------+--------------+---------------+ | Byte | 0 | 1 2 3 | 4 | 5 6 7 | 8 9 A B | C D E F | +------------+----+-----------+----+-----------+--------------+---------------+ | Descrption | BI | Start HCS | FD | End HCS | Start Sector | Num of Sector | +------------+----+-----------+----+-----------+--------------+---------------+ BI (1): Boot indicator (0x00 off, 0x80 on) Start HCS (3): Starting head, cylinder and sector FD (1): Filesystem descriptor End HCS (3): Ending head, cylinder and sector Start Sector (4): Starting sector (offset to disk start) Num of Sector (4): Number of sectors in partition
-
- 找 boot sector 比較關鍵的 assembly code 如下,在此不處理延伸分割區的情形。
-
- Booting DOS 類似 Booting A Program,把 DOS 磁區的第一個 sector 讀入交接即可。接下來該讀入的 DOS boot sector 會將 root directory 讀入 0x0000:0500,確認前兩個 entries 是 IO.SYS 以及 MSDOS.SYS 之後,將 IO.SYS 的前 3 個 sectors 讀入 0x0000:0700,並 jmp 過去將執行權交給 IO.SYS 持續接下來的開機程序。
- Booting FreeBSD 類似 Booting A Program,把 FreeBSD 磁區的第一個 sector 讀入交接即可,也就是三個 stage 中的 stage 1。此 sector 即為 /boot/boot0,載入執行後會將 boot sectors 也就是 slice 1 (FreeBSD 將 partition 稱為 slice) 的前 8192 bytes 讀入,進行 stage 2 booting。此時已有處理 file system 的能力,此時便可讀取檔案系統中的 kernel 進行 stage 3 完成開機。詳細情情可見下列二圖,並可參考來源網站取得進一步的細節。
-
- Booting Linux Linux 的 booting 動作較為複雜,必須先讀懂 ext3 file system 之後將起始檔案讀入後交接。詳細動作參考下圖:
-
- Operating System
- Interrupt 記憶體 0x00000 到 0x00400 存放著系統的 Interrupt Vector Table,每一個 entry 共 4 bytes,紀錄著該 interrupt 的 segment (2 bytes) 及 offset (2 bytes) 以便發生 interrupt 時能跳到對應的位置去執行對應的動作。X86 的 interrupt 可列表如下:
| | Common Uses |
| | |
| | Non-Maskable IRQ (Parity Errors) |
| | |
| | System Timer |
| | Keyboard |
| | Redirected |
| | Serial Comms. COM2/COM4 |
| | Serial Comms. COM1/COM3 |
| | Reserved/Sound Card |
| | Floppy Disk Controller |
| | Parallel Comms. |
| | |
| | Real Time Clock |
| | Redirected IRQ2 |
| | Reserved |
| | Reserved |
| | PS/2 Mouse |
| | Math's Co-Processor |
| | Hard Disk Drive |
| | Reserved |
| | |
-
- 當我們要實作自己的 interrupt,只需要更改對應號碼的內容即可,以下為關鍵的 software interrupt assembly code。此時若是 hardware interrupt,則當發生了該 interrupt 時,CPU 會馬上讀取 interrupt table 並跳至對應的位置 (在下面的例子即 myINT: 位址) 的部分去執行對應的動作;若是 software interrupt,則我們可以使用 "INT 數字" 來使用該 interrupt。目前常見 OS 的系統呼叫 (system call),便是用 software interrupt 配合 registers 當參數來完成,例如 DOS 使用 INT 0x21,而 Linux 則使用 INT 0x80。必須注意的是在 interrupt 發生的同時,CPU 會將 flags、cs、ip 依序 push 進 stack 中,而在 iret 時再 pop 出來繼續執行,因此在 interrupt 當中 stack 的任何更動都必須要小心處理。
myINT: cli ; We can do something here... sti iret ; interrupt return command ; install the interrupt cli push es ; Save es segment register xor ax, ax ; Zero ax mov es, ax ; Move 0000 into es. So loading the vector table segment mov WORD [es:0x20*4], myINT ; offset of INT 20 mov WORD [es:0x20*4+2], cs ; segment of INT 20 pop es sti
-
- 對於 hardware interrupt,則需要額外多做一些處理。當我們想要 enable/disable 某個 IRQ,必須更改對應 Programmable Interrupt Controller (PIC) 的 Operation Control Word (OCW) 內容。IRQ0 ~ IRQ7 的 disable bit 分別對應到 OCW1 (0x21) 之 bit0 ~ bit7,IRQ8 ~ IRQ15 則對應到 OCW2 (0xA1) 之 bit0 ~ bit7。此外,在 interrupt 結束前需送出 End Of Interrupt (EOI) 給對應的 PIC,對於 PIC1 是 outportb(0x20, 0x20);,對於 PIC2 則是 outportb(0xA0,0x20);。其中的 outportb(0xA0, 0x20) 在 asm 中為以下動作。
mov al, 0x20 out 0xA0, al
-
- 如果是以 C 來實作 hardware interrupt,則會類似以下 code。(以 IRQ1 也就是 INT 0x09 為例...)
-
- Device Driver 所謂的 device driver,說穿了就是 CPU 利用一連串的 I/O 來與 device 溝通,設定 device 的狀態、資料,或是由 device 讀取需要的資訊,可以說是軟硬體之間最底層的橋樑。I/O 方式有兩種:Direct I/O 及 Memory Mapped I/O。
-
- 一般而言,記憶體有自己的位址空間,I/O 也有自己的位址空間,而 Direct I/O 就是利用這樣的概念,mov BYTE [0x00], al 和 out 0x00, al 是兩件截然不同的事情。然而當我們為了使用上的方便,而將部份的 I/O 動作映射到記憶體空間時,就形成所謂的 Memory Mapped I/O,此時我們對該映射之記憶體空間做存取動作,就相當於對該 device 做 I/O 的動作。聽起來有點玄,以下便以最常見最基礎的 keyboard driver 和 VGA driver 為例來說明之。
- Keyboard Driver (INT 0x09, INT 0x16) 當我們想要從 keyboard 抓取使用者輸入時,通常會利用到 BIOS 的 INT 9 和 INT 16。其中 INT 9 為外部中斷,於使用者按下按鍵的瞬間產生中斷,將輸入的鍵值存入 BIOS 配置的 32 bytes (0x0040:001E ~ 0x0040:003D) 的 buffer 中;而 INT 16 則為內部中斷,若選項為讀取使用者之輸入,則會將 buffer 中的鍵值讀出到 al 暫存器。也就是說整個 keyboard 的運作流程可簡單示意如下圖。
- 送 command 0xAD 給 8042 keyboard microcontroller (port 0x64) 關閉鍵盤功能。
- 等待 8042 keyboard microcontroller (port 0x64) 回傳狀態 0x0A ACK。
- 由 on-board microcontroller (port 0x60) 回傳作對應的處理:
- 0xEE – Echo 訊息。
- 0xFA – Set ACK bit 訊息。
- 0xFE – Set Resend bit 訊息。
- 其他– 查表轉換成對應的 ASCII 碼,存入 BIOS buffer。
- 送 command 0xAE 給 8042 keyboard microcontroller (port 0x64) 開啟鍵盤功能。
- 等待直到 buffer 內有值。
- 取出 buffer 內的值。
- VGA Driver (INT 0x10) 最基本的 VGA card 將畫面資料對應到記憶體位址,因此存取畫面只需存取對應位址即可。其中單色系統由 0xB000:0000 開始,彩色系統由 0xB800:0000 開始,以 word 為單位 (ASCII I.O. byte + attribute H.O. byte),皆由 (0, 0) 對應到 (79, 24),一共 4000 bytes。彩色系統提供 8 個畫面空間可供切換,分別由 0xB000:0000、0xB000:1000、0xB000:2000、...、及 0xB000:7000 開始,而單色系統僅提供一個畫面。以下為顯示一個字元之程式碼,完全沒用到 in/out,非常之歡樂。; print al on location bx of screen #1 push es mov dx, 0xB800 mov es, dx shl bx, 0x01 mov BYTE [es:bx], al shr bx, 0x01 pop es 雖然 VGA 有 memory mapped I/O 很方便,但遇到顯示狀態或游標狀態的調整,還是得用 direct I/O 來操控相關的 CRT Controller (CRTC) Registers。其中 I/O port 0x03B4和0x03B5 (單色系統)、0x03D4和0x03D5 (彩色系統) 分別對應到 CRTC Address Register 和 CRTC Data Register 的存取。舉讀取游標位置為例,先設定 Address Register 再讀取 Data Register,以下為改變目前游標位置之程式碼。; read cursor location to bx push ax ; cursor location high mov al, 0x0E mov dx, 0x03D4 out dx, al mov dx, 0x03D5 in al, dx mov bh, al ; cursor location low mov al, 0x0F mov dx, 0x03D4 out dx, al mov dx, 0x03D5 in al, dx mov bl, al pop ax ;;;;; now we can do something here ;;;;; ; write cursor location from bx push ax ; cursor location high mov al, 0x0E mov dx, 0x03D4 out dx, al mov al, bh mov dx, 0x03D5 out dx, al ; cursor location low mov al, 0x0F mov dx, 0x03D4 out dx, al mov al, bl mov dx, 0x03D5 out dx, al pop ax 關於游標位置,BIOS 於 0x0040:0050 ~ 0x0040:005F 亦配置了八組暫存 words,我們也可以善加利用,才不用每次都要大費周章的讀取。
- Device Driver 補記 雖然表面上看起來就是一堆 in/out 好像很簡單,然而看了一下 ptt Tech_Job 板的討論,寫 driver 最大的瓶頸不在於照著規格書寫對應的功能,反而是 debug 的過程,常常會出現 bug 出在硬體或 OS 沒按照規格書實作的情形,要是硬體或 OS 廠商死不認帳,還是得自己一步步的找出癥結所在。有經驗的網友 diorite 說:「寫 Driver 的門檻只有兩個 - 不怕累、心要細,但是具備這兩個條件的人... 其實很難找。」又說:「常常都要一個人拿示波器坐在角落加班,沒有迫切金錢需要的人,通常是熬不住的。」話雖如此,就因為人才少,薪水分紅自然就比一般科技人高出許多,可以說是天下沒白吃午餐的最佳實例。
- Keyboard Driver (INT 0x09, INT 0x16) 當我們想要從 keyboard 抓取使用者輸入時,通常會利用到 BIOS 的 INT 9 和 INT 16。其中 INT 9 為外部中斷,於使用者按下按鍵的瞬間產生中斷,將輸入的鍵值存入 BIOS 配置的 32 bytes (0x0040:001E ~ 0x0040:003D) 的 buffer 中;而 INT 16 則為內部中斷,若選項為讀取使用者之輸入,則會將 buffer 中的鍵值讀出到 al 暫存器。也就是說整個 keyboard 的運作流程可簡單示意如下圖。
- Context Switch 所謂的 context switch,就是做程式的切換動作。大致上是將切換前的程式執行狀態存下來,並把打算執行程式的狀態回存出來,然後執行該程式。這時候會出現一些問題 (Who, When, Where, Why and How):
- Who - 需要存取哪些狀態? 一般而言不外乎暫存器 registers 和旗標 flags。這紀錄著程式執行到哪裡,以及一些不希望下次執行會被更動的值。
- When - 何時存取這些狀態? 在 user applications 切換之間,必須經過 OS 的 scheduler 來做排程管理。因此整個切換流程即 app1 -> OS scheduler -> app2,其中的兩個 "->" 便是存取狀態的時機。細部動作為:把 app1 的狀態存起來,讀回 OS 的狀態,scheduler 找出下一個要執行的程式,把 OS 的狀態存起來,讀回 app2 的狀態,執行 app2。
- Where - 要將這些狀態存在哪裡? 通常每個程式都會被 allocate 一塊專屬的 stack 空間,這就很好用啦!在程式切換的過程當中,只需要做更改 ss:sp 的動作,就可將不同的程式狀態存在它們各自的 stack 當中,既簡單又方便管理。當然,如果想存在自己另外定的記憶體區塊也沒問題,只是需要多做一些額外的管理就是了。
- Why - 為何要存取這些狀態? 在 single task 的 OS 中,一個程式執行完才能執行下一個程式,其實是不需要做這個動作的。然而在 multi-task 的 OS 中,一個程式執行到一半可能會被 interrupt 而轉換到另一個程式,若在切換前沒事先將狀態存下來,之後回到該程式一些狀態可能就不一樣了,這時候該程式應該會很不滿而做出一些詭異或是當機的動作。所以為了不讓程式有意見,還是存一下吧。
- How - 要如何存取這些狀態? 一言以敝之:push、pop。
pushf ; push flags as a wordpopf ; pop flags as a wordpusha ; push ax, cx, dx, bx, sp, bp, si, dipopa ; pop di, si, bp, sp, bx, dx, cx, ax
另外也要善加利用 call/ret 以及 int/iret 的特性。當我們執行 call addr 的時候,CPU 會將目前的 ip 暫存器 push 到 stack,再將 ip 設為 addr;而當我們執行 ret 的時候,CPU 會 pop 一個 word 到 ip 然後執行。同理 int/iret 也是一樣,只是 push/pop 的是 flags、cs、ip。
- 一般而言,記憶體有自己的位址空間,I/O 也有自己的位址空間,而 Direct I/O 就是利用這樣的概念,mov BYTE [0x00], al 和 out 0x00, al 是兩件截然不同的事情。然而當我們為了使用上的方便,而將部份的 I/O 動作映射到記憶體空間時,就形成所謂的 Memory Mapped I/O,此時我們對該映射之記憶體空間做存取動作,就相當於對該 device 做 I/O 的動作。聽起來有點玄,以下便以最常見最基礎的 keyboard driver 和 VGA driver 為例來說明之。
1. app1 running...2. interrupt3. context switch from app1 to kernel4. kernel scheduler pick next application to run5. context switch form kernel to app16. interrupt return7. app2 running...
-
- File System 一般而言,資料儲存設備之存取大都是以 sector 為單位,也就是 512 bytes。若任何的檔案大小都小於 512 bytes,我們大可不需要 file system,直接以 CHS 或 LBA 的方式來表示檔案即可。除非你是嵌入式系統的開發者或是史前時代的人類,不然我想一般人應該不會那麼做,一定會用到大於 512 bytes 的檔案,此時就要靠 file system 來管理檔案與儲存設備之間的對應關係。
-
- 至於 file system 的設計則端看各位開發者的想像力。以最常見最簡單的 FAT (File Allocation Table) 為例,以數個 sectors 集結為一個 cluster 作為單位,將檔案及目錄以 table 來做一對一的對應。當檔案超過一個 cluster 大小時,則以 chain 的方式串連到另外一個 cluster,以此類推。詳細的 FAT 架構可以參考
-
- ,這是目前看過最深入淺出的說明。
-
- 基於這樣的概念,結合 FAT 及 GMail 的 label 特性,小弟亦設計了一套非常破爛的 file system,姑且稱作 JasonmelFS,若有興趣可以參考報告用的
- 。
- Memory Management 在讀入檔案前,必須先知道該檔案要擺到記憶體哪個位置。位置的選擇,主要考量避免蓋掉其他使用中的檔案,並以發揮記憶體最大使用率,也就是盡可能的塞滿為依歸,同時演算法又不能太過遲鈍,這也正是 memory management 之所以困難的地方。為了避免蓋掉其他檔案,最簡單的做法便是使用 bitmap 的方式,以一對一的方式標記正在使用中的區塊,配置時就要避開這些位置。至於要如何充分利用記憶體以及有效率的演算法,就各憑本事了。
- Protected Mode under construction...
- 開機模擬動畫
- Reference Links
- (Keywords: X86, Booting, BIOS, BIOS_interrupt_call, Floppy_disk, Master_Boot_Record, Boot_sector)
- []