1. 程式人生 > >實模式和保護模式區別及尋址方式

實模式和保護模式區別及尋址方式

解釋 src 需求 範圍 上線 二進制表示 工作 菜鳥 相對

轉載自:http://blog.csdn.net/rosetta

64KB-4GB-64TB?

我記得大學的匯編課程、組成原理課裏老師講過實模式和保護模式的區別,在很多書本上也有談及,無奈本人理解和感悟能力實在太差,在很長一段時間裏都沒真正的明白它們的內含,更別說為什麽實模式下最大尋址空間為1MB?段的最大長度不超過64KB?而保護模式下為啥最大尋址能力就變成了64TB?每個段最大也達4GB? 更甚者分段和分頁這兩個高深的概念像我這種菜鳥怎麽也理解不了啊!

尋址能力都達64TB了,為啥我的電腦內存只有2GB呢?其實不用糾結於這事,這64TB就是所謂的虛擬地址空間,也叫邏輯地址空間,它能夠尋址這麽多,只是它有這個能力,並不代表你的內存就要裝這麽大,你內存比它小再多也不會影響你工作,反過來,要是它的尋址能力只有1MB,而你有2GB的內存,那麽那1.999GB就沒有實際用處了,這就太浪費資源了。而實際上這個64TB也沒有什麽實際意義,因為32位的地址總線能尋址的線性地址空間和物理地址空間都是2^32=4GB。這個64TB是怎麽出來的,稍後揭曉。

實模式與保護模式的來歷

我們先來說一下為什麽有實模式和保護模式的區別。最早期的8086 CPU只有一種工作方式,那就是實模式,而且數據總線為 16位,地址總線為20位,實模式下所有寄存器都是16位。而從80286開始就有了保護模式,從80386開始CPU數據總線和地址總線均為32位,而且寄存器都是32位。但80386以及現在的奔騰、酷睿等等CPU為了向前兼容都保留了實模式,現代操作系統在剛加電時首先運行在實模式下,然後再切換到保護模式下運行。

再來區別下幾個基本概念:邏輯地址、線性地址和物理地址。這些概念一時沒領會沒關系。繼續往下看。

三種地址

邏輯地址:即邏輯上的地址,實模式下由“段基地址+段內偏移”組成;保護模式下由“段選擇符+段內偏移”組成。

線性地址:邏輯地址經分段機制後就成線性地址,它是平坦的;如果不啟用分頁,那麽此線性地址即物理地址。

物理地址:線性地址經分頁轉換後就成了物理地址。

實模式尋址方式

剛才說了8086CPU數據總線為16位,也就是一次最多能取2^16=64KB數據,這個數據也解釋了實模式下為什麽每個段最大只有64KB。但剛才還說了其地址總線為20位,這樣它能尋址的能力其實是2^20=1MB,這也就是實模式下CPU的最大尋址能力。既然它有1MB尋址能力,那怎麽用16位的段寄存器表示呢?

這就引出了分段的概念,8086CPU將1MB存儲空間分成許多邏輯段,每個段最大限長為64KB(但不一定就是64KB)。這樣每個存儲單元就可以用“段基地址+段內偏移地址”表示。段基地址由16位段寄存器值左移4位表達,段內偏移表示相對於某個段起始位置的偏移量。比如:

SEG=0x07c0

jmpi offset, #SEG

offset: mov ax,cs

保護模式尋址方式

在定義“邏輯地址”時看到保護模式和實模式的區別在於它是用段選擇符而非段基地址,這也許就是保護模式的真諦所在,從段選擇符入手,全面理解保護模式編程基本概念和尋址方式。

分段機制

下面來看下保護模式是怎樣通過“段選擇符+段內偏移”尋址最終的線性地址或物理地址的。

圖1 邏輯地址到線性地址轉換,這裏的邏輯地址即指保護模式下的“段選擇符+段內偏移地址”,如果不啟用分頁管理的情況下,那麽此線性地址即最終的物理地址。

技術分享

圖1 邏輯地址到線性地址轉換

在理解此圖時必須要明白段選擇符結構、描述符表概念等,下面就一一介紹。

如圖2段選擇符結構,段選擇符為16位,它不直接指向段,而是通過指向的段描述符,段描述符(一會介紹)再定義段的信息。

技術分享

圖2 段選擇符結構

其中TI用來指明全局描述符表GDT還是局部描述符表LDT,RPL表示請求特權級,索引值為13位,所以從這裏看出,在保護模式下最多可以表示2^13=8192個段描述符,而TI又分GDT和LDT(如圖3所示),所以一共可以表示8192*2=16384個段描述符,每個段描述符可以指定一個具體的段信息,所以一共可以表示16384個段。而圖1看出,段內偏移地址為32位值,所以一個段最大可達4GB,這樣16384*4GB=64TB,這就是所謂的64TB最大尋址能力,也即邏輯地址/虛擬地址。

在保護模式實際編程中,如下一條語句:jmpi 0, 8。其中的8即段選擇符,8的二進制表示為:0000 0000 0000 1000b,所以這條語句的意思是跳轉到GDT表(TI=0)中的第2個(段描述符表從0開始編號,所以這裏的1指表中的第2個)段描述符定義的段中,其段內偏移為0。

技術分享

圖3

下面再來看段描述符結構,段描述符表中的每一項為一個段描述符,每一項為8字節,其結構如圖4所示。

技術分享

從圖中可知,段選擇符指向的段描述符裏有三個部分基地址信息,這三部分組成一個32位地址就決定了段基地址位置,此地址再加上段內偏移最終確定線性地址位置。

段描述符中的S位和TYPE字段(四位)的不同又分為數據段描述符、代碼段描述符(S=1)和系統段描述符(S=1)。數據段和代碼段描述符類型如圖5所示。

技術分享

圖5

系統段描述符如圖6所示。

技術分享

圖6

分頁機制

到目前為止我們知道了保護模式下是怎樣通過段選擇符指向一個段描述符,最終由段描述符+段內偏移定位線性地址,在不啟用分頁情況下,此線性地址就是物理地址,那麽在啟用分頁情況下,又是怎樣實現內存的映射轉換的呢?這就是偉大的分頁機制。

分頁機制如下圖所示,它把物理內存分成相同固定大小的頁面,2^12=4KB。每個頁面的0~4KB範圍由線性地址的低12位表示,線性地址空間的高10位用來指定頁目錄中的位置,可以選擇2^10=1024個目錄項,每個目錄項為四字節,所以頁目錄為1024*4B=4KB。每個目錄項中的高20位用以查找頁表在物理內存中的頁面,每個頁表含1024個頁表項,每個頁表項也是四字節,這樣一頁表也是1024*4B=4KB。所以一個頁目錄可以查找1024個頁表,每個頁表為4KB,所以總共可以查找的頁表大小為1024*4KB=4MB大。最後每個頁表項的高20位用以定位物理地址空間中的某個頁基地址,此地址再加上線性地址空間的偏移值就是最後物理內存空間單元。目錄項和頁表項結構如圖8所示。

技術分享

圖7分頁機制

技術分享

圖8

從一個邏輯地址經過分段和分頁尋址物理地址的整個過程就如圖9所示。總的來說整個過就是邏輯地址經分段機制變成線性地址,如果不啟用分頁的情況下,此線性地址就是物理地址;如果啟用分頁,那麽線性地址經分頁機制變成物理地址。

技術分享

圖9分段和分頁

分段和分頁的意義

說了半天分段和分頁的原理,它們到底有何用?這裏以保護模式下分段和分頁講解。

技術分享

圖10 多段模型

如圖10所示。一個多段模型充分發揮了段機制的對代碼、數據結構和程序提供硬件保護的能力。每個程序都有自己的段描述符表和自己的段。段可以完全屬於程序私有也可以和其它程序之間共享。

訪問權限的檢查不僅僅用來保護地址越界,也可以保護某一特定段不允許操作。例如代碼段是只讀段,硬件可以阻擊向代碼段進行寫操作。

分頁為需求頁、虛擬內存提供實現機制。具體的實現機制可以再深入學習。

文獻資料

《深入理解Linux內核》

《Linux內核完全剖析》趙炯

《Linux內核設計與實現》

《Linux內核修煉之道》

《新版匯編語言程序設計》錢曉捷著

《windows環境下32位匯編語言程序設計》羅雲彬著

實模式和保護模式區別及尋址方式