1>什麼是硬碟參數表
在PC機中BIOS設定的中斷向量表中int 0x41的中斷向量位置(4*0x41 =
0x0000:0x0104)存放的並不是中斷程式的地址,而是第一個硬碟的基本參數表
對於100%相容的BIOS來說,這裡存放著硬碟參數表陣列的首地址0xF000:0E401
第二個硬碟的基本參數表入口地址存於int 0x46中斷向量位置處.每個硬碟參
數表有16個位元組大小.
2>什麼是A20門
在8086/8088中,只有20根地址匯流排,所以可以訪問的地址是2^20=1M,但由
於8086/8088是16位地址模式,能夠表示的位址範圍是0-64K,所以為了在8086/
8088下能夠訪問1M記憶體,Intel採取了分段的模式:16位段基地址:16位位移.
其絕對位址計算方法為:16位基地址左移4位+16位位移=20位地址.
但這種方式引起了新的問題,通過上述分段模式,能夠表示的最大記憶體為:
FFFFh:FFFFh=FFFF0h+FFFFh=10FFEFh=1M+64K-16Bytes(1M多餘出來的部分被
稱做高端記憶體區HMA).但8086/8088隻有20位地址線,如果訪問100000h-
10FFEFh之間的記憶體,則必須有第21根地址線.所以當程式員給出超過1M
(100000H-10FFEFH)的地址時,系統並不認為其訪問越界而產生異常,而是自動
從重新0開始計算,也就是說系統計算實際地址的時候是按照對1M求模的方式
進行的,這種技術被稱為wrap-around.
到了80286,系統的地址匯流排發展為24根,這樣能夠訪問的記憶體可以達到
2^24=16M.Intel在設計80286時提出的目標是,在實模式下系統所表現的行為
應該和8086/8088所表現的完全一樣,也就是說,在實模式下80286以及後續系
列,應該和8086/8088完全相容.但最終,80286晶片卻存在一個BUG:如果程式員
訪問100000H-10FFEFH之間的記憶體,系統將實際訪問這塊記憶體,而不是象過去一
樣重新從0開始.
為瞭解決上述問題,IBM使用鍵盤控制器上剩餘的一些輸出線來管理第21
根地址線(從0開始數是第20根),被稱為A20 Gate.如果A20 Gate被開啟,則當
程式員給出100000H-10FFEFH之間的地址的時候,系統將真正訪問這塊記憶體區
域;如果A20 Gate被禁止,則當程式員給出100000H-10FFEFH之間的地址的時候,
系統仍然使用8086/8088的方式.絕大多數IBM PC相容機預設的A20 Gate是被
禁止的.由於在當時沒有更好的方法來解決這個問題,所以IBM使用了鍵盤控制
器來操作A20 Gate.在80286以及更高系列的PC中,即使A20 Gate被開啟,在實
模式下所能夠訪問的記憶體最大也只能為10FFEFH,儘管它們的地址匯流排所能夠
訪問的能力都大大超過這個限制.為了能夠訪問10FFEFH以上的記憶體,則必須進
入保護模式.
A20,其實它就是對於20-bit(從0開始數)的特殊處理(也就是對第21根地
址線的處理).如果A20 Gate被禁止,對於80286來說其地址為24bit,其地址表
示為EFFFFF;對於80386極其隨後的32-bit晶片來說,其地址表示為FFEFFFFF.
這種表示的意思是如果A20 Gate被禁止,則其第20-bit在CPU做地址訪問的時
候是無效的,永遠只能被作為0;如果A20 Gate被開啟,則其第20-bit是有效,
其值既可以是0,又可以是1.
所以,在保護模式下,如果A20 Gate被禁止,則可以訪問的記憶體只能是奇數
1M段,即1M,3M,5M…,也就是00000-FFFFF,200000-2FFFFF,300000-3FFFFF….
如果A20 Gate被開啟,則可以訪問的記憶體則是連續的.
3>如何開啟A20地址線
多數PC都使用鍵盤控制器(8042晶片)來處理A20 Gate.從理論上講,開啟
A20 Gate的方法是通過設定8042晶片輸出連接埠(64h)的2nd-bit,但事實上,當
你向8042晶片輸出連接埠進行寫操作的時候,在鍵盤緩衝區中,或許還有別的數
據尚未處理,因此你必須首先處理這些資料.
處理過程如下:
1. 禁止中斷;
2. 等待,直到8042 Input buffer為空白為止;
3. 發送禁止鍵盤操作命令到8042 Input buffer;
4. 等待,直到8042 Input buffer為空白為止;
5. 發送讀取8042 Output Port命令;
6. 等待,直到8042 Output buffer有資料為止;
7. 讀取8042 Output buffer,並儲存得到的位元組;
8. 等待,直到8042 Input buffer為空白為止;
9. 發送Write 8042 Output Port命令到8042 Input buffer;
10. 等待,直到8042 Input buffer為空白為止;
11. 將從8042 Output Port得到的位元組的第2位置1(OR 2),然後寫入8042
Input buffer;
12. 等待,直到8042 Input buffer為空白為止;
13. 發送允許鍵盤操作命令到8042 Input buffer;
14. 開啟中斷。
4>如何檢測A20地址線是否開啟
我們在之前已經提到,如果A20 Gate被開啟了,則在實模式下,程式員可以
直接存取100000H~10FFEFH之間的記憶體,如果A20 Gate被禁止,則在實模式下,
若程式員訪問100000H~10FFEFH之間的記憶體,則會被硬體自動轉換為0H~0FFEFH
之間的記憶體,所以我們可以利用這個差異來檢測A20 Gate是否被開啟.
5>CR0寄存器
CR0寄存器是處理器4個控制寄存器之一,結構如下
+----+--------------------------+----+----+----+----+----+
| PG | Reserved | ET | TS | EM | MP | PE |
+----+--------------------------+----+----+----+----+----+
31 30 5 4 3 2 1 0
BIT 0:PE 如果該位被置位,則運行保護模式,否則運行實模式
BIT 1:MP 控制wait指令
BIT 2:EM 表示副處理器功能是否可以被模擬
BIT 3:TS 用於任務轉換
BIT 4:ET 表示當前副處理器的類型(80287或80387)
BIT 31:PG表示處理器是否使用分頁機制
6>描述符表
在保護模式下記憶體的定址方式跟實模式下不同,它並不是簡單的將段寄存
器的16位地址左移4位,然後加上位移量來構成20位地址.在保護模式下,是可
以定址4GB空間的,因為有32跟地址線,所以2^32 = 4GB.在該模式下是通過段
寄存器的索引值在描述符表(通用描述元表GDT或者局部描述符表LDT)內尋找
到相應的表項,然後通過擷取表項裡儲存的段基地址,段基地址與位移量相加
得到線性地址.如果系統沒採用分頁處理模式,那麼線性地址就對應著實際的
物理地址了.分頁處理模式放到記憶體管理文檔裡詳細說明.
段寄存器格式:
+--------------------------------+------+-----+
| Index | TI | RPL |
+--------------------------------+------+-----+
15 32 1 0
RPL: 優先順序別 0 - 4 LINUX只用了0核心態 3使用者態
TI: 0使用通用描述元表(GDT),1使用局部描述符表(LDT)
描述符表是儲存在gdtr或者ldtr寄存器裡的,該寄存器共佔用6個位元組大
小.0-15位是表限,16-47位是表的基地址.表限是表示該表的大小,基地址是表
示描述符表所在的線性地址中的位置.
全域描述符號表和局部描述符號表的結構是一樣的,如下:
+---------------------------------+----------+
| Base address | Limit |
+---------------------------------+----------+
47 1615 0
描述符表項是儲存在描述符表裡的內容.Intel公司將表項的第一個項設
為空白,從第2個表項開始使用.描述符表項的結構定義如下:
63 5655 5251 4847 4039 3231 1615 87 0
+---------+----+-------+-----+---------+-------------+-----------------+
|B31 - B24| |L19-L16| |B23 - B16|基地址 B15-B0|段上限L15 - L0|
+---------+----+-------+-----+---------+-------------+-----------------+
+------+------+------+------+
| G | D/B | O | AV |
+------+------+------+------+
55 52
G: =1 段長以4K位元組為單位 =0 段長以位元組為單位
D/B: =1 表示對該段訪問為32位指令 =0 表示為16位指令
O: 永遠為0
AV: 可由軟體使用,CPU忽略該位
+-----+----------+-----+-----+-------+-------+------+
| P | DPL | S | E | ED/C | R/W | A |
+-----+----------+-----+-----+-------+-------+------+
47 44 43 40
A: =1 已經被訪問過 =0 還未被訪問過
R/W: ---+
ED/C: ---|----+---> +---- E = 0 資料區段
E: ---+ | |
| +---- ED = 0 向上伸(資料區段) ED = 1 向下伸(堆棧段)
| |
| +---- W = 0不可寫 W = 1 可寫
|
+---> +---- E = 1程式碼片段
|
+---- C = 0 忽略特權級 C = 不忽略特權級
|
+---- R = 0 不能讀 R = 1可讀
S = 0表示用於系統管理的系統段 = 1表示一般的程式碼片段或者資料區段
DPL: 特權級
P = 1該段在記憶體中 = 0 不在記憶體中
|
1樓
硬碟基本參數表
中斷向量表中,int 0x41 的中斷向量位置(4 * 0x41 =0x0000:0x0104)存放的並不是中斷程式的地
址而是第一個硬碟的基本參數表。對於100%相容的BIOS 來說,這裡存放著硬碟參數表陣列的首地址
F000h:E401h。第二個硬碟的基本參數表入口地址存於int 0x46 中斷向量中。
表 硬碟基本參數資訊表
位移 大小 說明
0x00 字 柱面數
0x02 位元組 磁頭數
0x03 字 開始減小寫電流的柱面(僅PC XT 使用,其它為0)
0x05 字 開始寫前預補償柱面號(乘4)
0x07 位元組 最大ECC 猝髮長度(僅XT 使用,其它為0)
0x08 位元組 控制位元組(磁碟機步進選擇)
位0 未用
位1 保留(0) (關閉IRQ)
位2 允許複位
位3 若磁頭數大於8 則置1
位4 未用(0)
位5 若在柱面數+1 處有生產商的壞區圖,則置1
位6 禁止ECC 重試
位7 禁止訪問重試。
0x09 位元組 標準逾時值(僅XT 使用,其它為0)
0x0A 位元組 格式化逾時值(僅XT 使用,其它為0)
0x0B 位元組 檢測磁碟機逾時值(僅XT 使用,其它為0)
0x0C 字 磁頭著陸(停止)柱面號
0x0E 位元組 每磁軌扇區數
0x0F 位元組 保留。
硬碟裝置號命名方式
硬碟的主裝置號是3。其它裝置的主裝置號分別為:
1-記憶體,2-磁碟,3-硬碟,4-ttyx,5-tty,6-並行口,7-非具名管道
由於1 個硬碟中可以存在1--4 個分區,因此硬碟還依據分區的不同用次裝置號進行指定分區。因此
硬碟的邏輯裝置號由以下方式構成:
裝置號=主裝置號*256 + 次裝置號
也即dev_no = (major<<8) + minor
兩個硬碟的所有邏輯裝置號見下表所示。
表 硬碟邏輯裝置號
邏輯裝置號 對應裝置檔案說明
0x300 /dev/hd0 代表整個第1 個硬碟
0x301 /dev/hd1 表示第1 個硬碟的第1 個分區
0x302 /dev/hd2 表示第1 個硬碟的第2 個分區
0x303 /dev/hd3 表示第1 個硬碟的第3 個分區
0x304 /dev/hd4 表示第1 個硬碟的第4 個分區
0x305 /dev/hd5 代表整個第2 個硬碟
0x306 /dev/hd6 表示第2 個硬碟的第1 個分區
0x307 /dev/hd7 表示第2 個硬碟的第2 個分區
0x308 /dev/hd8 表示第2 個硬碟的第3 個分區
0x309 /dev/hd9 表示第2 個硬碟的第4 個分區
其中0x300 和0x305 並不與哪個分區對應,而是代表整個硬碟。
從linux 核心0.95 版後已經不使用這種煩瑣的命名方式,而是使用與現在相同的命名方法了。
5.4.3.5 硬碟分區表
為了實現多個作業系統共用硬碟資源,硬碟可以在邏輯上分為1--4 個分區。每個分區之間的扇區號
是鄰接的。分區表由4 個表項組成,每個表項由16 位元組組成,對應一個分區的資訊,存放有分區的大小
和起止的柱面號、磁軌號和扇區號,見下表所示。分區表存放在硬碟的0柱面0頭第1個扇區的0x1BE--0x1FD
處。
表 硬碟分區表結構
位置 名稱 大小 說明
0x00 boot_ind 位元組 引導標誌。4 個分區中同時只能有一個分區是可引導的。
0x00-不從該分區引導作業系統;0x80-從該分區引導操作
系統。
0x01 head 位元組 分區起始磁頭號。
0x02 sector 位元組 分區起始扇區號(位0-5)和起始柱面號高2 位(位6-7)。
0x03 cyl 位元組 分區起始柱面號低8 位。
0x04 sys_ind 位元組 分區類型位元組。0x0b-DOS; 0x80-Old Minix; 0x83-Linux …
0x05 end_head 位元組 分區的結束磁頭號。
0x06 end_sector 位元組 結束扇區號(位0-5)和結束柱面號高2 位(位6-7)。
0x07 end_cyl 位元組 結束柱面號低8 位。
0x08--0x0b start_sect 長字 分區起始物理扇區號。
0x0c--0x0f nr_sects 長字 分區佔用的扇區數。
__ |
bios執行完後把硬碟的參數放在某個地方,其入口地址由中斷向量號0x41指定
中斷向量0x41的地址是4*0x41(每個向量四個位元組)
用bochs查看[xp/11x 0x104]
0x00000104 <bogus+ 0>: 0x9fc0003d 0xf000ff53 0xc0002544
0xf000ff53
可見入口地址為:0x9fc0003d
又入口地址的前個位元組為位移量(0x003d),後兩個位元組為段地址(0x9fc0),所以物理地址為9fc00+003d=0x9fc3d
查看硬碟參數表[xp/11x 0x9fc3d]
0x0009fc3d <bogus+ 0>: 0x00040132 0x00ffff00 0x000000c0
0x00110132
第0,1位元組為柱面數,即0x0132(不是0x3201),第2個位元組為磁頭數0x04,倒數第二個位元組為沒磁軌扇區數,即0x11
硬碟可以看成一個圓柱,三個參數為:
磁頭,哪個面
柱面,哪個圈
扇區,圈上哪個弧