Intel X86 CPU系列尋址方式

  X86體系

Intel所謂的X86體系,是指Intel從16位微處理器8086開始的整個CPU芯片系列,系列中的每種型號都保持與以前的各種型號兼容,主要有8086,8088,80186,80286,80386,80486以及以後各種型號的Pentium芯片。該篇文章主要是結合Linux內核的儲存管理對其尋址方式做一些簡要的說明

  在X86體系中,8086和8088是16位的處理器,而從80386開始爲32位處理器,80286是從8088到80386,也就是從16位處理器過渡到32位的一箇中間過程。80286雖然還是16位的處理器,但是從尋址方式上開始了從“實地址模式”到“保護地址模式”的過渡。

  知識小解:

  1. 當我們說CPU是“16位”或“32位”時,指的是什麼?

      指的是處理器中“算術邏輯單元”(ALU全稱:Arithmetic Logic Unit)的寬度。系統總線中的數據線部分,稱爲“數據總線”通常和ALU有着相同的寬度。同樣的最自然的地址總線也是與數據總線一致。但是實際中有可能不同。

  2.MMU:內存管理單元,也稱爲“地址翻譯器”,全稱爲 Memory Manage Unit。

  3.GDT(Global Descriptor Table):相當於一個64bit 的數組。但是爲了前後兼容性,其裏面存放的是16bit的內容,是數組的                                                                下標,index。

  4.GDTR:段描述符表可以存放在內存的任何一個位置上,當程序員通過段寄存器來引用一個段描述符的時間,CPU必須知道                       GDT的入口地址。而GDTR就是用來存放這個GDT基地址的寄存器。

  5. 地址之間的轉換:

  實地址模式歷史發展:

   起初,先從8位CPU的尋址能力的角度來看,這樣一個8位的地址只能用來尋訪256個不同的地址單元,這顯然太小了,實際上也就是不現實的,所以在那個年代就設置成了8位CPU16位的地址總線,這也造成了內部結構不對稱的問題。

  後來,當CPU的技術從8位發展到16位之後,本來地址總線的寬度和數據總線的寬度可以一致了,但是現實和歷史總是驚人的相似,人們覺得16位的地址總線,也就是尋址範圍(64K)還是太小了。那麼該增加多少呢???但是結合微型機的應用前景和儲存器芯片的價格,Itel決定採用1M(20位),當時已經很大了。

  Itel決定了其16位CPU,即8086中採用1M字節的內存地址空間,地址總線的寬度即爲20位,但是我們的CPU的ALU卻只有16位!如何解決這個問題呢???

  Itel當時結合MMU,設計了一種“分段”的技術。Itel在8086 CPU中設置了四個“段寄存器”: CS DS SS ES(指令,數據,堆棧,其他),每個段寄存器都是16位的,對於地址總線的高16位。則每條訪問指令中的“內部地址”都是高16位這樣就實現了從16位的內部地址到20位的實際地址的轉換(也稱爲“映射”

  這種模式的內存管理最大的缺陷就是:沒有地址空間的保護機制。對於每一個由段寄存器的內容確定的“基地址”,一個進程總是能夠訪問從此開始的64K字節的連續地址空間,而無法進行相應的控制。同時可以用來改變段寄存器內容的指令也不是什麼“特權指令”,也就是說可以通過改變段寄存器的內容,任何一個進程便可以隨心所欲的訪問內存中的任何一個單元,而絲毫不受限制。

  不能對一個進程的內存訪問加以限制,也就談不上什麼內存管理。於是“保護地址模式”出現了。Intel從80286開始實現了其“保護地址模式”,但是早期的80286只能從實地址模式轉入到保護地址模式,卻不能從保護地址模式轉回實地址模式。隨着後來的發展,下面將以80386爲例子進行介紹保護地址模式。

  保護地址模式的發展:

   80386是個32位CPU,也就是其ALU數據總線是32位的,當他的地址總線寬度和數據總線一致,即尋址範圍到達了4G,它的內存來說似乎已經足夠了,那麼是否可以重新設計一個32位的CPU呢???答案是肯定的,不能!!!。作爲該系列產品中的一員,80386必須維持那些段寄存器,還必須支持實地址模式,與此同時還能支持保護地址模式。這該怎麼做呢???

  思路分析:Intel選擇了在段寄存器的基礎上構建保護模式的構思,並且保留段寄存器爲16位(這樣才能利用原來的四個段寄存器)同時又添加了兩個段寄存器FS和GS。爲實現保護模式,光利用一個段寄存器來確定它的基地址是不是夠的,至少還得要一個地址段的長度,以及其它的一些權限等信息。所以這裏需要設計一個數據結構,而並非一個單純的基地址。

  解決辦法:在保護模式下改變段寄存器的功能,使其從一個單純的基地址變成指向這樣的一個數據結構。這樣當一條內存指令發出一個內存地址時,CPU就可以這樣來歸納出實際上應該放上數據總線的地址:

① 根據指令的性質,確定使用哪個段寄存器。

② 根據段寄存器的內容,找到相應的地址段描述結構

③ 從地址段描述結構中得到基地址。

④ 將指令中發出的地址作爲地址偏移量,與段描述結構中規定的段長度相比,看看是否越界。

⑤ 根據指令的性質和段描述符中的訪問權限來確定是否越權。

⑥ 將指令中發出的地址作爲偏移,與基地址相加得到相應的物理地址。

  一:80386的段式內存管理機制

  比較容易理解了。首先,在80386 CPU中增設了兩個寄存器:一個全局性的段描述表寄存器GDTR(global descriptortable register),另一個是局部性的段描述表寄存器LDTR(local descriptor table register),分別用來指向儲存在內存中的一個段描述結構,稱之爲“段描述表”,並且訪問這兩個段寄存器的指令都設置爲了“特權指令”。

  在此基礎上,段寄存器的高13位用作訪問段描述表中具體描述結構的下標(index),如下圖:

 

所以:將段寄存器內容的低3位屏蔽掉以後與GDTR或LDTR中的基地址相加得到的描述表象的起始地址。每個段描述表項的大小是8個字節:包含 段的基地址和段的大小,再加上一些其他的信息,如下圖:詳細介紹(https://blog.csdn.net/genzld/article/details/83750730

小結:

  80386當一個段寄存器的內容改變時,CPU會根據新的段寄存器內容和GDTR和LDTR中的內容找到相應的段描述項並將其裝入到CPU中。在此過程中,CPU會檢查該描述符項中的p標誌位(present),如果標誌爲0,則表示該描述表項所指的那段內容不在內存中(即:在磁盤的某個位置),CPU會產生異常(類似中斷),相應的服務器程序便可以從磁盤交換分區將這一段的內容讀入內存的某一個地方,據此設置該描述表項的基地址,再將p設置爲1.相應的內存中的暫時不用的儲存段則可以寫入磁盤,其p標誌位設置爲0。

  80386主要通過設置系統狀態和用戶狀態來實現保護機制,那麼怎麼實現兩種機制之間的切換呢?

80386並非只是劃分出了系統狀態和用戶狀態,而是劃分成了四種特權級別,其中0級最高,3級別最低。一般程序的當前運行級別由其代碼段的局部描述項(由段寄存器CS所指向的局部短描述項)中的dpl(descriptor privilege level)字段決定.同時該字段是在0級狀態下的內核設定的。而全局段描述的dpl字段,則有不同,它是表示所需的級別。

  下面來看一下16位段寄存器的結構:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章