1. 程式人生 > >x86 真實模式與保護模式

x86 真實模式與保護模式

0386開始,CPU有三種工作方式:真實模式保護模式虛擬8086模式。只有在剛剛啟動的時候是real-mode,等到作業系統執行起來以後就切換到protected-mode。真實模式只能訪問地址在1M以下的記憶體稱為常規記憶體,我們把地址在1M 以上的記憶體稱為擴充套件記憶體。在保護模式下,全部32條地址線有效,可定址高達4G位元組的實體地址空間; 擴充的儲存器分段管理機制和可選的儲存器分頁管理機制,不僅為儲存器共享和保護提供了硬體支援,而且為實現虛擬儲存器提供了硬體支援; 支援多工,能夠快速地進行任務切換(switch)保護任務環境(context); 4個特權級和完善的特權檢查機制,既能實現資源共享

又能保證程式碼和資料的安全和保密及任務的隔離; 支援虛擬8086方式,便於執行8086程式。

真實模式(Real Mode)

它是 Intel公司80286及以後的x86(80386,8048680586)相容處理器CPU)的一種操作模式。真實模式被特殊定義為20位地址記憶體可訪問空間上,這就意味著它的容量是220次冪(1M)的可訪問記憶體空間(實體記憶體和BIOS-ROM),軟體可通過這些地址直接訪問BIOS程式和外圍硬體。真實模式下處理器沒有硬體級記憶體保護概念和多道任務的工作模式。但是為了向下相容,所以80286及以後的x86系列相容處理器仍然是開機啟動時工作在真實模式下80186和早期的處理器僅有一種操作模式,就是後來我們所定義的真實模式。真實模式雖然能訪問到

1M的地址空間,但是由於BIOS的對映作用(即BIOS佔用了部分空間地址資源),所以真正能使用的實體記憶體空間(記憶體條),也就是在640k924k之間。1M 地址空間組成是由 16位的段地址和16位的段內偏移地址組成的。用公式表示為:實體地址=左移4位的段地址+偏移地址

286處理器體系結構引入了地址保護模式的概念,處理器能夠對記憶體及一些其他外圍裝置做硬體級的保護設定(保護設定實質上就是遮蔽一些地址的訪問)。使用這些新的特性,然而必不可少一些額外的在80186及以前處理器沒有的操作規程。自從最初的x86微處理器規格以後,它對程式開發完全向下相容,80286晶片被製作成啟動時繼承了以前版本晶片的特性,工作在真實模式下,在這種模式下實際上是關閉了新的保護功能特性,因此能使以往的軟體繼續工作在新的晶片下。直到今天,

甚至最新的x86處理器都是在計算機加電啟動時都是工作在真實模式下,它能執行為以前處理器晶片寫的程式.

DOS作業系統(例如 MS-DOS,DR-DOS)工作在真實模式下,微軟Windows早期的版本(它本質上是執行在DOS上的圖形使用者介面應用程式,實際上本身並不是一個作業系統)也是執行在真實模式下,直到Windows3.0,它執行期間既有真實模式又有保護模式,所以說它是一種混合模式工作。它的保護模式執行有兩種不同意義(因為80286並沒有完全地實現80386及以後的保護模式功能)

1〉“標準保護模式”:這就是程式執行在保護模式下;

2〉“虛擬保護模式(實質上還是真實模式,是真實模式上模擬的保護模式)”:它也使用32位地址定址方式。Windows3.1徹底刪除了對真實模式的支援。在80286處理器晶片以後,Windows3.1成為主流作業系統(Windows/80286不是主流產品)。目前差不多所有的X86系列處理器作業系統(LinuxWindows95 and laterOS/2等)都是在啟動時進行處理器設定而進入保護模式的。

真實模式工作機理:

1> 對於8086/8088來說計算實際地址是用絕對地址對1M求模8086地址線的物理結構:20,也就是它可以物理定址的記憶體範圍為2^20個位元組,即1 M空間,但由於8086/8088所使用的暫存器都是16位,能夠表示的地址範圍只有0-64K,這和1M地址空間來比較也太小了,所以為了在8086/8088下能夠訪問1M記憶體,Intel採取了分段定址的模式:16位段基地址:16位偏移EA。其絕對地址計算方法為:16位基地址左移4+16位偏移=20位地址。  比如:DS=1000H EA=FFFFH 那麼絕對地址就為:10000H +
0FFFFH = 1FFFFH 地址單元
 。通過這種方法來實現使用16位暫存器訪問1M的地址空間,這種技術是處理器內部實現的,通過上述分段技術模式,能夠表示的最大記憶體為:
 
FFFFh: FFFFh=FFFF0h+FFFFh=10FFEFh=1M+64K-16Bytes1M多餘出來的部分被稱做高階記憶體區HMA。但8086/8088只有20位地址線,只能夠訪問1M地址範圍的資料,所以如果訪問100000h~10FFEFh之間的記憶體(大於1M空間),則必須有第21根地址線來參與定址(8086/8088沒有)。因此,當程式設計師給出超過1M100000H-10FFEFH)的地址時,因為邏輯上正常,系統並不認為其訪問越界而產生異常,而是自動從0開始計算,也就是說系統計算實際地址的時候是按照對1M求模的方式進行的,這種技術被稱為wrap-around

2> 對於80286或以上的CPU通過A20 GATE來控制A20地址線  技術發展到了 80286,雖然系統的地址匯流排由原來的20根發展為24根,這樣能夠訪問的記憶體可以達到2^24=16M,但是Intel在設計80286時提出的目標是向下相容,所以在真實模式下,系統所表現的行為應該和8086/8088所表現的完全一樣,也就是說,在真實模式下,80386以及後續系列應該和8086/8088完全相容仍然使用A20地址線。所以說80286晶片存在一個BUG:它開設A20地址線。如果程式設計師訪問100000H-10FFEFH之間的記憶體,系統將實際訪問這塊記憶體(沒有wrap-around技術),而不是象8086/8088一樣從0開始。我們來看一副圖:


為了解決上述相容性問題,IBM使用鍵盤控制器上剩餘的一些輸出線來管理第21根地址線(從0開始數是第20根) 的有效性,被稱為A20 Gate

1> 如果A20 Gate被開啟,則當程式設計師給出100000H-10FFEFH之間的地址的時候,系統將真正訪問這塊記憶體區域;

如果A20 Gate被禁止,則當程式設計師給出100000H-10FFEFH之間的地址的時候,系統仍然使用8086/8088的方式即取模方式(8086模擬)。絕大多數IBM PC相容機預設的A20 Gate是被禁止的。現在許多新型PC上存在直接通過BIOS功能呼叫來控制A20 Gate的功能。

保護模式(Protected Mode)

上面所述的記憶體訪問模式都是真實模式,在80286以及更高系列的PC中,即使A20 Gate被開啟,在真實模式下所能夠訪問的記憶體最大也只能為10FFEFH,儘管它們的地址匯流排所能夠訪問的能力都大大超過這個限制。為了能夠訪問10FFEFH以上的記憶體,則必須進入保護模式。

(286Intel 80286的另一種叫法)它又被稱作為虛擬地址保護模式。儘管在Intel 80286手冊中已經提出了虛地址保護模式,但實際上它只是一個指引,真正的32位地址出現在Intel 80386上。保護模式本身是80286及以後相容處理器序列之後產成的一種操作模式,它具有許多特性設計為提高系統的多道任務系統的穩定性。例如記憶體的保護分頁機制硬體虛擬儲存的支援。現代多數的x86處理器作業系統都執行在保護模式下,包括Linux, Free BSD, Windows3.0(它也執行在真實模式下,為了和Windows 2.x應用程式相容)及以後的版本。

80286及以後的處理器另一種工作模式是真實模式(僅當系統啟動的一瞬間),本著向下相容的原則遮蔽保護模式特性,從而容許老的軟體能夠執行在新的晶片上。作為一個設計規範,所有的x86系列處理器,除嵌入式Intel80387之外,都是系統啟動工作在真實模式下,確保遺留下的作業系統向下相容。它們都必須被啟動程式(作業系統程式最初執行程式碼)重新設定而相應進入保護模式的,在這之前任何的保護模式特性都是無效的。在現代計算機中,這種匹配進入保護模式是作業系統啟動時最前沿的動作之一。

在被調停的多道任務程式中,它可以從新工作在真實模式下是相當可能的。保護模式的特性是阻止被其他任務或系統核心破壞已經不健全的程式的執行,保護模式也有對硬體的支援,例如中斷執行程式,移動執行程序文件到另一個程序和置空多工的保護功能。

386及以後系列處理器不僅具有保護模式又具有32位暫存器,結果導致了處理功能的混亂,因為80286雖然支援保護模式,但是它的暫存器都是16位的,它是通過自身程式設定而模擬出的32位,並非32位暫存器處理。歸咎於這種混亂現象,它促使Windows/386及以後的版本徹底拋棄80286的虛擬保護模式,以後保護模式的作業系統都是執行在80386以上,不再執行在80286(儘管80286模式支援保護模式),所以說80286是一個過渡晶片,它是一個過渡產品

儘管 286386處理器能夠實現保護模式和相容以前的版本,但是記憶體的1M以上空間還是不易存取,由於記憶體地址的迴繞,IBM PC XT (現以廢棄)設計一種模擬系統,它能過欺騙手段訪問到1M以上的地址空間,就是開通了A20地址線。在保護模式裡,前32箇中斷為處理器異常預留,例如,中斷0D(十進位制13)常規保護故障和中斷00是除數為零異常。

如果要訪問更多的記憶體,則必須進入保護模式,那麼,在保護模式下, A20
Gate對於記憶體訪問有什麼影響呢?

為了搞清楚這一點,我們先來看一看A20的工作原理。A20,從它的名字就可以看出來,其實它就是對於A20(從0開始數)的特殊處理(也就是對第21根地址線的處理)。如果A20 Gate被禁止,對於80286來說,其地址為24根地址線,其地址表示為EFFFFF;對於80386極其隨後的32根地址線晶片來說,其地址表示為FFEFFFFF。這種表示的意思是:


1> 如果A20
Gate被禁止。則其第A20CPU做地址訪問的時候是無效的,永遠只能被作為0。所以,在保護模式下,如果A20
Gate被禁止,則可以訪問的記憶體只能是奇數1M段,即1M,3M,5M…,也就是00000-FFFFF, 200000-2FFFFF,300000-3FFFFF…

2如果A20 Gate被開啟。則其第20-bit是有效的,其值既可以是0,又可以是1。那麼就可以使A20線傳遞實際的地址訊號。如果A20 Gate被開啟,則可以訪問的記憶體則是連續的。

真實模式和保護模式的區別

從表面上看,保護模式和真實模式並沒有太大的區別,二者都使用了記憶體段、中斷和裝置驅動來處理硬體,但二者有很多不同之處。我們知道,在真實模式中記憶體被劃分成段,每個段的大小為64KB,而這樣的段地址可以用16位來表示。記憶體段的處理是通過和段暫存器相關聯的內部機制來處理的,這些段暫存器(CSDSSSES)的內容形成了實體地址的一部分。具體來說,最終的實體地址是由16位的段地址和16位的段內偏移地址組成的。用公式表示為:實體地址 = 左移 4 位的段地址 + 偏移地址。

在保護模式下,段是通過一系列被稱之為描述符表的表所定義的。段暫存器儲存的是指向這些表的指標。用於定義記憶體段的表有兩種:全域性描述符表(GDT)區域性描述符表 (LDT)GDT是一個段描述符陣列,其中包含所有應用程式都可以使用的基本描述符。在真實模式中,段長是固定的(64KB),而在保護模式中,段長是可變的,其最大可達4GBLDT也是段描述符的一個數組。與GDT不同,LDT是一個段,其中存放的是區域性的、不需要全域性共享的段描述符。每一個作業系統都必須定義一個 GDT ,而每一個正在執行的任務都會有一個相應的 LDT 。每一個描述符的長度是 8 個位元組,格式如圖3所示。當段暫存器被載入的時候,段基地址就會從相應的表入口獲得。描述符的內容會被儲存在一個程式設計師不可見的影像暫存器(shadow register)之中,以便下一次同一個段可以使用該資訊而不用每次都到表中提取。實體地址由16位或者32位的偏移加上影像暫存器中的基址組成。真實模式和保護模式的不同可以從下圖很清楚地看出來。


真實模式地址


保護模式地址


總結

保護模式同真實模式的根本區別是程序記憶體受保護與否。可定址空間的區別只是這一原因的果。真實模式將整個實體記憶體看成分段的區域,程式程式碼和資料位於不同區域,系統程式和使用者程式沒有區別對待,而且每一個指標都是指向"實在"的實體地址。這樣一來,使用者程式的一個指標如果指向了系統程式區域或其他使用者程式 區域,並改變了值,那麼對於這個被修改的系統程式或使用者程式,其後果就很可能是災難性的。為了克服這種低劣的記憶體管理方式,處理器廠商開發出保護模式。這 樣,實體記憶體地址不能直接被程式訪問,程式內部的地址(虛擬地址)要由作業系統轉化為實體地址去訪問,程式對此一無所知。

至此,程序有了嚴格的邊界,任何其他程序根本沒有辦法訪問不屬於自己的實體記憶體區域,甚至在自己的虛擬地址範圍內也不是可以任意訪問的,因為有一些虛擬區域已經被放進一些公共系統執行庫。這些區域也不能隨便修改,若修改就會有: SIGSEGV(linux 段錯誤);非法記憶體訪問對話方塊(windows 對話方塊)。

CPU啟動環境為16位真實模式,之後可以切換到保護模式。但從保護模式無法切換回真實模式 。

對於80X86處理器來說,從80386處理器開始,除了以前的真實模式外,還增添了 
保護模式和V86模式。真實模式和V86模式都是為了和8086相容而設定的。 

真實模式: 
      記憶體定址方式為:段式定址,即實體地址=段地址*16   +   段內偏移地址 
      可定址任意地址,所有指令都相當於工作在特權級。 
      dos工作在真實模式下 
保護模式: 
      記憶體定址方式為:支援記憶體分頁和虛擬記憶體 
      支援多工,可依靠硬體用一條指令即可實現任務切換,不同任務可工作在 不同的優先順序下,作業系統工作在最高優先順序0上,應用程式則執行       在較低優先順序 上。從真實模式到保護模式,需要建立GDT、IDT等資料表,然後通過修改控制寄存 器CR0的控制位(位0)來實現。 
      Windows工作在保護模式下。 
虛擬8086模式: 
        記憶體定址方式:段式定址,與真實模式一樣 
        支援多工和記憶體分頁 
        v86模式主要是為了在保護模式下相容以前的真實模式應用,即可支援多工, 
        但每個任務都是真實模式的工作方式。 

另外,中斷和異常等的處理對於不同的工作模式都是不同的,具體的可以去 參看一些相關書籍。 


以上轉自:http://blog.csdn.net/kennyrose/article/details/7563649

以下轉自:http://ahhqlrg.lofter.com/post/1ccdac85_7882945

 Intel的真實模式和保護模式,必須要知道的...

一、Intel手冊如是說 

        Intel的IA-32架構支援三種基本操作模式:保護模式、實地址模式和系統管理模式。操作模式決定了哪些指令和架構相關的特性是可用的:

  • 保護模式(protected mode)——是處理器的根本模式,在保護模式下,可以為直接執行的實地址模式程式提供保護的、多工的環境,這種特性被稱作“虛擬8086模式(virtual 8086 mode)”,儘管“虛擬8086”模式並不是一種真正的處理器模式;virtual 8086 mode實際上是保護模式的一種屬性,在保護模式下,可以向任何任務提供這種屬性。
  • 實地址模式(real-addess mode)——該模式以擴充套件的方式實現了8086CPU的程式執行環境(就像切換到保護模式和系統管理模式一樣)。處理器在剛剛上電或者重啟後的時候,處於實地址模式。
  • 系統管理模式(system manangement mode,SMM)——該模式提供作業系統或者執行程式一種透明的機制去實現平臺相關的特性,例如電源管理和系統安全。當來自外部的或者APIC控制器的SMM中斷pin腳被觸發時,處理器在下列情況進入SMM。在SMM下,處理器切換到一個獨立的地址空間,同時儲存當前執行的程式或任務的上下文。SMM相關的程式碼可透明的執行。當SMM模式返回時,處理器返回SMI(system manangement interrupt)前的工作模式。SMM模式在Intel 386 SL和Intel 486 SL處理器時被引入,在Pentium家族時成為標準的IA-32架構的特性。

        Intel 64 架構增加了IA-32e模式,IA-32e模式又包含兩種子模式:

  • 相容模式(Compatibility mode)——相容模式允許絕大部分16-bit/32-bit的應用可以無需重新編譯就能直接在64bits的作業系統下執行。簡單的,在IA-32架構下將“相容子模式”稱為“相容模式”。相容模式的可執行環境與Section 3.2定義的一致。相容模式也支援所有的特權級別,在64-bit和保護模式下。執行在虛擬8086模式下的或用到硬體任務管理的程式,在此模式下無法工作。相容模式做程式碼段基礎被作業系統所啟動,這意味著單獨的64-bit作業系統可以通過64-bit模式支援64-bit應用,也可以通過相容模式支援32-bit程式(無需再編譯)。相容模式類似於32-bit的保護模式,應用程式只能訪問前4G的線性地址空間。相容模式使用16-bit和32-bit的地址以及運算元長度。類似於保護模式,該模式允許應用程式通過PAE(實體地址擴充套件,Physical Address Extention)訪問超過4G的實體記憶體。
  • 64-bit模式(64-bit  mode)——該模式使作業系統在64-bit線性地址空間上執行應用程式,在IA-32架構下,64-bit子模式被簡稱為64-bit模式。64-bit模式將通用暫存器和SIMD暫存器從8個擴充套件到16個。通用暫存器被增加到64bits寬。該模式還引入了新的運算元字首(REX)來訪問暫存器擴充套件。64-bit模式作為程式碼段基礎被作業系統啟用,該模式預設地址長度是64bits,但預設運算元長度為32bits,預設的運算元長度可以在指令級別被覆蓋,通過使用REX運算元字首結合運算元大小覆蓋字首。REX字首被用來在64-bit模式下指定一個64-bit的運算元,通過這種機制,很多已經存在的指令程式碼可以被直接升級到訪問64-bit地址空間和64-bit暫存器。        
二、真實模式的歷史原因 

        早在1978年,Intel研製了8086處理器,8086處理有16-bit暫存器和16-bit的外部資料匯流排,但是卻能夠訪問20-bit的地址(包含1MByte的地址空間)。8086通過引入“分段(segmentation)機制”來解決這個問題。在分段機制下,一個16bits的段暫存器包含了一個長度是64KBytes的“段”空間的起始指標。通過1次時可用一個段暫存器,8086處理器可以無需在段間切換就能定址高達256KBytes。因此,通過段暫存器+16bits的指標就能訪問20bits的地址空間,共1Mbytes。

        雖然8086/8088處理器採用的地址空間大小與外部匯流排位寬不一致,但是這顯得很“彆扭”,並且在1985年80386時被統一,地址空間和外部匯流排位寬均為32bits。

        為了相容8086,這種分段管理記憶體的方式一直被保留下來。當然,真實模式不僅僅是分段記憶體管理,而是“程式的執行環境”,所為的執行環境,還包括暫存器的長度。

三、真實模式和保護模式的區別 

        個人理解,因為x86的CPU在啟動時首先處於真實模式,也就8086的16位模式,主要特點有:

  • 記憶體管理採用段+偏移的方式進行;
  • 最大尋指位2的20次方,即1Mbyte;
  • 沒有安全級別,直接操作CPU的各種功能;
  • 沒有分頁功能,沒有虛擬地址的概念,只有實體地址;
  • 各種暫存器的位寬基本上是16位的(段暫存器為20位);

        真實模式就是一種比較原始的模式,能看到CPU設計的初始過程。

        保護模式是32位模式,但是可以相容16位的真實模式,保護模式的特點有:

  • 記憶體管理採用段式+頁式的方式;
  • 最大尋指位2的32次方,即4G,還可以通過PAE模式訪問超過4G的部分。
  • 有4個安全級別,記憶體操作時有安全檢查;
  • 因為有了分頁功能,因此有虛擬地址和實體地址的區別;
  • 各種暫存器的位寬基本上都是32位的,但是可以相容同名的16位暫存器;
  • 可以相容實地址模式,也即實地址模式的程式無需再編譯即可跑在保護模式下。

        對於64位CPU來說,相容模式和64位模式也基本上一個道理,相容模式為了相容32位,也就相容了16位,而64位模式本身不去相容32位,是純淨的64位。

四、真實模式對OS的意義 

        僅從Linux作業系統考慮。因為32位CPU一上電後,首先處於真實模式下,所以真實模式是OS必須經歷的一種模式。既然保護模式可以相容真實模式,那麼CPU為什麼還要提供專門的真實模式呢?是否OS可以直接從真實模式跳轉到保護模式呢?

        實話說,這兩個問題我也不太好回答。為了錢?對Linux系統來說,從真實模式到保護模式的過程,實際上主要就是為了初始化保護模式的過程。從實際模式切換到保護模式不是開開關、按按鈕,而需要準備工作,主要是為了開啟分頁機制做準備,要分頁,必須有頁表、段描述符,這些都需要通過記憶體初始化。關於具體的過程,請參考《Linux核心啟動保護模式的過程》。

        個人認為真實模式就是在CPU啟動的時刻的低階模式,需要OS無需在該模式上做過多的事情,而僅僅為向高階模式轉化做準備。