為了給之後的虛拟位址映射總結作準備,本篇先來看看什麼是實位址模式、什麼是保護模式。。。→_→
Intel的CPU發展也是經過技術不斷地疊代更新,才有了今天的成就(但依舊逃不掉牙膏廠的美譽。。→_→)。是以在不同的技術時期,其CPU也采用了不同的尋址方式
- 實位址模式
- 在80286之前都采用這種尋址重點内容模式。比如在8086中雖然有20位位址總線,但CPU中的ALU的寬度卻隻有16位。于是為了解決尋址問題,采用了“分段”的方法。在8086 CPU中設定了四個段寄存器“CS、DS、SS、ES”,每個段寄存器都是16位的,對應于位址總線的高16位。每條指令中的邏輯位址也是16位的,是以位址要被送上位址總線之前,其高12位要與對應的段寄存器相加,而低4位不變,即
- 實際位址 = (段寄存器的值 << 4)+ 邏輯位址
- 實位址模式也稱為實模式,在實模式中沒有相應的位址空間保護機制,通過段寄存器可以通路從此開始的64K連續位址空間。而且更改段寄存器的指令沒有“特權要求”,是以一個程序可以通路任何一個記憶體單元
- 保護模式(Protected Mode)
- 為了解決實位址模式中的安全問題而設計的一種尋址機制。從80286開始實作了部分保護模式,80386開始完全實作了保護模式與實模式的轉化。80386是32位CPU,為了與之前的系列保持一緻,保留了16位的段寄存器,增加了兩個段寄存器FS、GS。
- 為了實作保護模式,設計使段寄存器從單純的基位址變成一個資料結構指針,當一條指令通路記憶體位址時的步驟如下
- 根據指令的性質确定使用哪一個段寄存器
- 根據段寄存器的内容,找到相應的位址段描結構
- 從位址段描述結構中得到基位址
- 将指令要通路的位址作為位移,與段描述結構中規定的段長度比較,檢查是否越界
- 根據指令的性質和段描述結構中的通路權限确定是否越權
- 将指令要通路的記憶體位址作為位移,與基位址相加得到實際的實體位址
- 具體實作
- 在80386中增設兩個寄存器:全局性段描述表寄存器GDTR(Global Descriptor Table Register )和局部性段描述表寄存器LDTR(Local Descriptor Table Register )。其用來指向一個存儲在記憶體的段描述結構數組(段描述表)而且通路這兩個寄存器的指令是特權指令,這樣做是為了防止沒有權限的程序修改段寄存器或段描述結構等非法通路操作
- 圖中解釋段寄存器的字段含義,根據TI字段選擇使用哪一種段描述表寄存器,段寄存器給出的下标和GDTR和LDTR中的基位址相結合,得到段描述表項的基位址 圖中解釋段描述符表項的字段含義,每個段描述表項為8位元組 圖中解釋段描述符表項的TYPE字段含義 段描述表項的僞代碼
typedef struct { unsigned int base24_31:; /*基位址的高8位 */ unsigned int g:; /* granularity,表段的長度機關,0表示位元組,1表示 4KB */ unsigned int d_b:; /* default operation size ,存取方式,0表示16位,1表示32位 */ unsigned int unused:; /*固定設定成0 */ unsigned int avl:; /* avalaible,可供系統軟體使用*/ unsigned int seg_limit_16_19:; /* 段長度的高4位 */ unsigned int p:; /* segment present,為0時表示該段不在記憶體中*/ unsigned int dpl:; /* Descriptor privilege level,通路本段所需的權限 */ unsigned int s:; /* 描述項類型,1表示系統,0表示代碼或資料 */ unsigned int type:; /* 段的類型,與S标志位一起使用*/ unsigned int base_0_23:; /* 基位址的低24位 */ unsigned int seg_limit_0_15:; /* 段長度的低16位 */ };
- 80386中四個特權級别,0級最高,3級最低。每一條指令都有其适用級别,通常使用者程式都是3級,一般程式的運作級别由代碼段的局部描述項DPL字段決定,這是由0級狀态下的的核心設定的。當改變一個寄存器内容時,CPU對權限進行檢查,確定該程式的執行權限和段寄存器所制定要求的權限RPL所要通路的記憶體的權限DPL
*本篇的内容其實很雜,開始寫的時候很糾結如何一篇就說清楚虛拟位址映射,發現比較難。。。是以就先把一些重要的點總結出來。。。→_→*