尋訪x86處理器「實模式」和「保護模式」的前世今生

2021-07-15 21:48:53 字數 4226 閱讀 6415

我想我並沒有明白段的對映方法和意義

尋訪x86處理器「實模式」和「保護模式」的前世今生

2013-04-07 23:45:46

分類: linux

還是把博文「cpu的內部架構和工作原理」裡的這個表搬出來,祭奠那些不應該在歲月的洪荒中被淹埋的榮耀:

8086的誕生,標誌著intel 正式進入了x86時代,這是個多麼具有紀念意義的日子:1978-6-8。同時,8086的誕生也是處理器記憶體定址技術的第一次飛躍。

對於一根實際的、實實在在的、物理的、可看得見、摸得著的記憶體條而言,處理器把它當做8位乙個位元組的序列來管理和訪問,每乙個記憶體位元組都有乙個對應的位址,我們叫它實體地址,用位址可以表示的長度叫做定址空間。而cpu是如何去訪問記憶體單元裡的資料的方式就叫做定址。

8086得cpu在記憶體定址方面第一次引入了乙個非常重要的概念----段。在8086之前都是4位機和8位機的天下,那是並沒有段的概念。當程式要訪問記憶體時都是要給出記憶體的實際實體地址,這樣在程式源**中就會出現很多硬編碼的實體地址。這樣的程式可想而知,難重定位,可控性弱,結構醜陋,那個年**這樣的程式在我們現在看來是多麼讓人惱火的一件事兒。

8080問世後四年也就是2023年,intel開始設計16位cpu,正常來說8086的定址空間應該是216=64kb才對,但intel就偏偏不這幹,8086的目標定址空間直指1m,也就是說8086的位址匯流排位寬要達到20位。如何讓16位的內部暫存器對20位的外部位址空間進行定址,intel的工程師們從當時的pdp-11小型機身上找到了靈感。pdp-11是美國迪吉多電腦(digital equipment corp.)公司於1970到2023年代熱銷的16位迷你電腦,pdp-11的記憶體管理單元(mmu)可以將16位位址對映到24位位址空間裡(至於人家是怎麼弄,我就真不曉得了)。

為了支援分段機制,intel在8086的cpu裡新增了4個暫存器,分別是**段cs,資料段ds,堆疊段ss和其他es(以後深入介紹一下這幾個兄弟夥,這涉及到程序的在記憶體的運**況)。這樣一來,乙個實體地址就由兩個部分組成,分別是「段位址」:「段內偏移量」。例如,es=0x1000,di=0xffff,那麼這個資料es:di在記憶體裡的絕對實體地址就是:

ad(absolute address)=(es)*(0x10)+(di)=0x1ffff

就是講段基位址左移4位然後加上段內偏移量就得到了物理記憶體裡的絕對位址,經過這麼乙個變換,就可以得到乙個20位的位址,8086就可以對20位的1m記憶體空間進行定址了。如下:

很明顯,這種方式可以定址的最高位址為0xffff:0xffff,其位址空間為0x00000~0x10ffef,因為8086的位址匯流排是20位,最大只能訪問到1mb的實體地址空間,即實體地址空間是0x00000~0xfffff。當程式訪問0x100000~0x10ffef這一段位址時,因為其邏輯上是正常的,cpu並不會認為其訪問越界而產生異常,但這段位址確實沒有實際的實體地址與其對應,怎麼辦?此時cpu採取的策略是,對於這部分超出1m位址空間的部分,自動將其從物理0位址處開始對映。也就是說,系統計算實際實體地址時是按照對1m求模運算的方式進行的,在有些技術文獻裡你會看到這種技術被稱之為wrap-around。還是通過一幅圖來描述一下吧:

根據前面的講解我們可以發現段基址有個特徵,其低4位全為0,也就是說每個段的起始位址一定是16的整數倍,這是分段的乙個基本原則。這樣每個段的最小長度是16位元組,而最大長度只能是64kb。這裡我們可以計算一下,1mb的實體地址空間能劃分成多少個段。

如果每個段的長度為16位元組,這樣1mb實體地址空間最多可以劃分成64k個段;

如果每個段的長度為64kb,那麼1mb的實體地址空間最多能劃分成16個段。

8086這種分段基址雖然實現了定址空間的提公升,但是也帶來一些問題:

1、同乙個實體地址可以有多種表示方法。例如0x01c0:0x0000和0x0000:0x1c00所表示的實體地址都是0x01c00。

2、位址空間缺乏保護機制。對於每乙個由段暫存器的內容確定的「基位址」,乙個程序總是能夠訪問從此開始64kb的連續位址空間,而無法加以限制。另一方面,可以用來改變段暫存器內容的指令也不是什麼「特權指令」,也就是說,通過改變段暫存器的內容,乙個程序可以隨心所欲地訪問記憶體中的任何乙個單元,而絲毫不受限制。不能對乙個程序的記憶體訪問加以限制,也就談不上對其他程序以及系統本身的保護。與此相應,乙個cpu如果缺乏對記憶體訪問的限制,或者說保護,就談不上什麼記憶體管理,也就談不上是現代意義上的**處理器。

總結一下:8086和後來的80186,這種只能訪問1mb位址空間的工作模式,我們將其稱之為「實模式」。我的理解就是「實際位址模式」,因為通過段基址和段偏移算出來的位址,經過模1mb之後得出來的位址都是實際記憶體的實體地址。

由於8086的上述問題,2023年,intel在80286的cpu裡,首次引入的位址保護的概念。也就是說80286的cpu能夠對記憶體及一些其他外圍裝置做硬體級的保護設定(實質上就是遮蔽一些位址的訪問)。自從最初的x86微處理器規格以後,它對程式開發完全向下相容,80286晶元被製作成啟動時繼承了以前版本晶元的特性,工作在實模式下,在這種模式下實際上是關閉了新的保護功能特性,因此能使以往的軟體繼續工作在新的晶元下。後續的x86處理器都是在計算機加電啟動時都是工作在實模式下。

也就是說,在保護模式下,程式不能再隨意的訪問物理記憶體了,有些記憶體位址cpu做了明確的保護限制。

2023年80386的問世,使intel完成了從16位到32位cpu的飛躍,這中間80286毫無疑問的就成了這次飛躍的跳板。80286的位址線已經達到24位,可定址空間是16mb,但intel當初設計80286時提出的目標是向下相容,這也是intel一貫的作風,正是這種作風為intel後面設計80386時增添了幾根兒煩惱絲。所以,在「實模式」下,80286所表現的行為和8086所表現的完全一樣。

80386是32位cpu,也就是說它的alu資料匯流排是32位,位址匯流排的位寬和cpu內部資料匯流排的位寬是一致的,都是32位,其定址範圍可達4gb。如果重新設計80386的架構,其結構應該相當簡潔才對。但是80386卻很遺憾的無法做到這一點,作為乙個產品系列中的成員分子,80386必須繼續維持「前輩」們的那些段暫存器,必須支援實模式,同時還要支援保護模式。可以看得出來,80386其實也不容易。

所以,intel決定在80386的段暫存器(cs,ds,ss,es)的基礎上構築保護模式,並且繼續保留段暫存器為16位,同時又增添了兩個段暫存器fs和gs。顯然,為了實現保護模式,光是用段暫存器來確定乙個基位址是不夠的,至少還要有乙個位址段的長度,並且還需要一些諸如訪問許可權之類的其他資訊。所以,這裡需要的是乙個資料結構(這個資料結構就叫做「段描述符」,以後會看到),而並非乙個單純的基位址。對此, intel設計人員的基本思路是:

在保護模式下改變段暫存器的功能,使其從乙個單純的段基址變成指向乙個「段描述符」的指標。因此,當乙個訪存指令發出乙個記憶體位址時, cpu按照下面過程實現從指令中的32位邏輯位址到32位線性位址,再到實體地址的轉換:

1、首先根據指令的性質來確定該使用哪乙個段暫存器,例如操作指令中的位址在**段cs裡,而資料指令中的位址在資料段ds裡。這一點與實位址模式相同。

2、根據段暫存器裡的內容,找到相應的「段描述符」結構。

3、然後,從「段描述符」裡得到的才是段基址。

4、將指令中的位址作為偏移量,然後和段描述符結構中規定的段長度進行比較,看齊是否越界。

5、根據指令的性質和段描述符中的訪問許可權來確定當前指令操作是否越權。

6、最後才將指令中的位址作為偏移量,與段基址相加得到線性位址,或者叫虛擬位址。

7、最後根據線性位址算出實際的實體地址。

所以,實模式就是80186及其之前的cpu只能定址1mb實體地址空間,且尋到的就是實實在在的實體地址的模式,使用者程式想幹啥幹啥,無法無天;而保護模式,就是說使用者成的程式,某些位址你是不能訪問的,或者說是有限制性的訪問,且你訪問到的位址不再是實體地址了,而是乙個虛擬的位址。這個虛擬位址要經過一系列演算法處理,最終對映到實際實體地址單元裡去。

現在執行在x86cpu上的主流作業系統,如linux,freebsd,windows95以後的版本以及os/2等都是工作在保護模式下。一般情況下,處理器只有在上電啟動,引導階段,初始化系統時才會進入實模式,當實模式階段的任務完成後,它就切換到了保護模式。當切換到保護模式後就很難再回到實模式了,幾乎

不可能。(注意我的用詞)

未完,待續…

尋訪x86處理器「實模式」和「保護模式」的前世今生

原文 還是把博文 cpu的內部架構和工作原理 裡的這個表搬出來,祭奠那些不應該在歲月的洪荒中被淹埋的榮耀 8086的誕生,標誌著intel 正式進入了x86時代,這是個多麼具有紀念意義的日子 1978 6 8。同時,8086的誕生也是處理器記憶體定址技術的第一次飛躍。對於一根實際的 實實在在的 物理...

X86處理器架構

包含有暫存器 算術邏輯單元 控制單元 時鐘位址 資料 控制匯流排1 將想要讀讀取的值的位址放在位址匯流排上。2 設定處理器rd 讀取 引腳 改變rd的值 3 等待乙個時鐘週期給儲存器晶元進行響應。4 將資料從資料匯流排複製到目標運算元。1 cpu從被稱為指令佇列的記憶體區域取得指令,之後立即增加指令...

《ubuntu下x86彙編》之x86處理器

一 處理器基本資訊 cat proc cpuinfo processor 0 vendor id genuineintel cpu family 6 model 23 model name pentium r dual core cpu e5500 2.80ghz processor 1 vendo...