⚠這篇文章比較無聊,因為涉及到一些硬件相關的東西,所以大部分的知識內容都很刻板,基本只能當作字典用。

之前講了關於主引導扇區上的內容,這次就來講講BootLoader具體是怎麼編寫和加載系統的.

首先我們需要知道硬盤是如何工作的,以及它的結構。

🤣服了,搞個軟件還得知道硬件的工作方法就離譜。

首先每個扇區的大小是固定在512字節的,現代硬盤的尋址方式一般都是通過LBA(邏輯塊尋址)來進行。老式的叫做CHS(柱面-磁頭-扇區)。這篇文章主要使用的是LBA28方式,也就是最高支持28位尋址。

當下的計算機應該採用的是更高位的LBA了。不過基本原理都是差不多的。

硬盤內部也是存在類似寄存器的結構,我們在彙編中會用端口的方式來訪問它們。

端口地址作用說明
0x1F0數據寄存器負責數據管理,用於讀取或寫入數據
0x1F1錯誤寄存器 / 特性寄存器記錄錯誤信息(讀)、設置功能(寫)
0x1F2扇區計數寄存器指定待讀取或寫入的扇區數
0x1F3LBA 低 8 位LBA 地址的 0-7 位
0x1F4LBA 中 8-15 位LBA 地址的 8-15 位
0x1F5LBA 高 16-23 位LBA 地址的 16-23 位
0x1F6設備寄存器選擇主盤/從盤,LBA 高 24-27 位
0x1F7狀態寄存器 / 命令寄存器讀時返回狀態,寫時執行命令

數據寄存器(0x1F0)

  • 作用:用於 讀取/寫入數據,一次傳輸 16 位(2 字節)。
  • 數據大小:一個扇區(512 字節)= 256 次 16 位傳輸。

扇區計數寄存器(0x1F2)

  • 作用:指定要讀/寫的 扇區數。
  • 數值範圍:1-255,0 表示 256 個扇區。

LBA 地址寄存器

LBA 地址由 28 位組成,分佈在 4 個寄存器:

端口地址寄存器位範圍作用
0x1F3LBA 低 8 位0-7LBA 低 8 位
0x1F4LBA 中 8-15 位8-15LBA 中 8 位
0x1F5LBA 高 16-23 位16-23LBA 高 8 位
0x1F6LBA 最高 4 位 + 設備選擇24-27LBA 最高 4 位

設備/磁盤選擇寄存器(0x1F6)

  • 作用:選擇 主盤 / 從盤,並存儲 LBA 最高 4 位。
描述
7必須為 1
61 = LBA 模式,0 = CHS 模式
5必須為 1
40 = 主盤,1 = 從盤
3LBA 地址的 第 24 位
2LBA 地址的 第 25 位
1LBA 地址的 第 26 位
0LBA 地址的 第 27 位

狀態寄存器(0x1F7,讀)

  • 作用:用於檢查硬盤狀態,確定何時可以讀取/寫入數據。
名稱描述
7BUSY1 = 硬盤忙,無法執行新命令
6DRDY1 = 硬盤準備就緒
5DF1 = 磁盤錯誤(寫保護或數據錯誤)
4SEEK COMPLETE1 = 磁頭已定位到正確位置
3DRQ1 = 數據準備就緒(可讀/寫)
2CORR1 = 硬盤糾錯
1IDX索引標誌(幾乎不使用)
0ERR1 = 發生錯誤

命令寄存器(0x1F7,寫)

  • 作用:向 0x1F7 端口寫入命令,通知硬盤執行相應的操作。
  • 使用方式:在正確設置 LBA 地址和扇區數 後,向該寄存器寫入相應命令。
命令值功能
0x20讀取扇區(LBA 模式)
0x30寫入扇區(LBA 模式)
0xEC識別硬盤信息
0xE7刷新硬盤緩存
0xF8設備重置

LBA 方式讀取磁盤

LBA 是現代磁盤的標準尋址方式,它將磁盤看作 連續的扇區序列,計算方式如下:

1LBA 地址 = (柱面號 × 磁頭數 + 磁頭號) × 每磁道扇區數 + 扇區號 - 1

LBA 讀取磁盤步驟

  • 選擇通道: 向 0x1F2(扇區計數寄存器)寫入 待讀取的扇區數。
  • 設置 LBA 地址: 1、將 LBA 低 24 位 寫入 0x1F3、0x1F4、0x1F5;2、將 LBA 高 4 位 寫入 0x1F6,並置位第 6 位(LBA 模式)。
  • 發送讀取命令: 向 0x1F7(命令寄存器)寫入 0x20(讀取扇區命令)。
  • 檢查狀態: 讀取 0x1F7(狀態寄存器),確認硬盤數據準備就緒。
  • 讀取數據: 從 0x1F0 讀取 512 字節(1 個扇區)到內存。

知道了上述知識,我們就知道了如何控制硬盤,接下來我們可以開始編寫BootLoader辣!