80386保護模式總結

2021-05-11 07:18:21 字數 4019 閱讀 4073

大學也上過微機原理,但那個時候整天玩php,vc++,c# .net...資料庫管理系統...沒有意識到她是一門非常重要的課。於是上這些基礎課的時候都在下面看那些***從入門到精通之類的書了或者乾脆翹了去圖書館看(當然我不會否認正是因為這些書讓我玩計算機的興趣堅持了下去)。大學畢業同學都把書賣了。我當時感到像微機原理組成原理之類的書可能以後有用,於是沒有賣(因為我知道自己的興趣所在)。 畢業後感覺那些***從入門到精通之類的書太無聊也太多。更多的是興趣吧,於是慢慢的啃起微機原理,作業系統來了。 廢話還是少說,總結下80386保護模式記憶體定址。防止以後忘了可以看看,再者希望有相同興趣的人看到了減少他們的彎路和指出我理解的錯誤。

一、概括對比下8086和80386的定址

8086的邏輯位址由16位的段位址和16位的段內偏移組成。定址方式:段位址由使用者程式指定,儲存在段暫存器中。以後程式直接使用段內偏移位址(就是段內的偏移量)就行了。記憶體定址時(如何得到物理記憶體位址): 1.取得相應的段位址(儲存段暫存器中)。 2.取得偏移位址(這個一般都是指令中給出的)。 3.經過乙個運算規則a 4.得到物理記憶體位址

80386的邏輯位址是也分兩部分:16位段選擇子+32位段內偏移。定址方式:邏輯位址(這裡用虛擬位址合理)在程式編譯時候決定(可能是作業系統,編譯器,聯結器給出的)。記憶體定址時: 1.取得相應的段選擇子(儲存段暫存器中)。(段選擇子其實還是在16位段暫存器中。只是名字改了而已。後面會說明為什麼) 2.取得偏移位址(這個一般都是指令中給出的)。 3.經過乙個運算規則b 4.得到物理記憶體位址(如果沒有分頁)

從上面可以看出從8086到80386段記憶體管理是本質上是一樣的。都是通過段暫存器和偏移位址來定址:定址方式可表示成段暫存器:[段內偏移] 不同的地方是從8086到80386上面的步驟3中的運算規則和偏移位址長度改變了而已。

現在具體寫下步驟3中的位址運算規則: 運算規則a(8086): 20位的實體地址 = 段位址(16位)*10h + 段內偏移(16位) 這就是傳說中的段位址左移四位+偏移位址形成20位實體地址。運算規則b(8386): 1.根據段選擇子找到段基位址(32位) 2.32位實體地址 = 段基位址(32位) + 段內偏移(32位) 之所以叫80386改名叫選擇子時因為段基位址是由段暫存器中的內容選擇出來的。其實這一切還是很簡單。要說複雜那就是80386多了些計算步驟而已。但是不用擔心。這些定址由硬體完成不用你自己計算。

最後要說明的是80386還多了乙個分頁的功能,這個功能是可選的。要是啟用分頁,上面得到位址其實是線性位址,還要變換才能形成實體地址。

二、相關暫存器和資料結構

這個地方可以先隨便看看(但是很重要的其實),不懂的繞過。等看到看下面可以返回來查閱。

descriptor 描述符乙個固定結構的結構體(struct)長度是8位元組也就是64位,那麼這個結構體是幹嘛的呢?用來描述乙個段基位址。這個結構體內容包括段基位址,段長度,段屬性。這個被描述的段基位址就是上面我們說的 32位實體地址 = 段基位址(32位) + 段內偏移(32位) 中的段基位址。描述符有兩種,也就是說這種結構體有兩種不同的結構(其實其中包含的內容都幾乎一樣只有一些細小的差別)。一種用來描述資料段,**段和堆疊段的,稱為非系統描述符,另一種就是用來描述ldt和tss的,(ldt和tss在後面有說明)稱為系統段描述符。

gdt 全域性描述符表(global descripter table) 顧名思義,就是乙個表而已。這個表儲存在記憶體中,相當於乙個結構體陣列。陣列的每一項就是上面所說的描述符了。這個表中可以包含四種資訊的描述符。1.全域性的資料段**段堆疊段,這些段一般作業系統核心使用。(每個單獨的使用者任務由ldt描述,ldt後面有說明) 2.對ldt的描述 這個描述符的基址就是是ldt所在記憶體中的起始位址 3.對tss的描述 這個描述符的基址是tss所在記憶體中的起始位址 4.一些門描述符(呼叫門,中斷門...) 其中#1用的是上面說的非系統段描述符,#2,#3,#4用的是系統段描述符。不同門買描述符,ldt,tss雖然都用系統段描述符但是其中一些屬性值用拉區分不同的描述符。 btw:ldt,tss都是屬於每個任務的所以一般成對出現在gdt中。

gdtr 全域性描述符表暫存器(global descripter table register) gdtr就是乙個暫存器,和ax bx.. cs ds...乙個概念。這個暫存器共有48位。其中32位位址指出gdt在記憶體中的位置(可以說這個是乙個32位的實體地址,如果沒有分頁開啟),另外16位為gdt的大小(gdt最多可以有多少項)。

ldt 區域性描述符表(local descripter table) 和gdt的結構差不多,所不同的是ldt只是包含對具體每個使用者任務的**段堆疊段資料段描述(當然就沒有包含對tss,和ldt的描述項了).

ldtr 區域性描述符表暫存器(global descripter table register) ldtr和gdtr一樣也是暫存器,不同的是它只有16位大小。為什麼不和gdtr不是48位呢?原因如下: 1.gdt在乙個多工系統中一般只有乙個,所以基址由乙個gdtr確定,之後幾乎不會改變。但是ldt的數量是可以和使用者任務相等的,就是每個使用者任務都可能擁有自己的ldt,這裡ldtr不方便和gdtr一樣使用乙個48位的暫存器給出基址,因為任務的切換這個之前基址就丟失了。任務就切換不回來了。或者任務切換回來重建自己的ldt,效率很低。 2.ldtr中存放的是乙個16位選擇子,根據這個選擇子去在gdt中定址找到ldt的基址。換句話說:全域性描述符表(gdt)的基址是存在gdtr中的(就是說gdt靠gdtr定位),而區域性描述符表(ldt)的基址是存在gdt中的,作為gdt這張表中的一項描述的(注意,前面我們說過gdt中描述符項包括對ldt段的描述)。 ldtr當作為選擇子,ldt作為一項在gdt中描述好處在於:每個使用者任務的區域性描述符表(ldt)的起始記憶體位址放在gdt中,這樣切換任務的時候只要改變選擇子就能實現ldt的切換,而且由於每個ldt在gdt中都有描述,不會丟失,方便任務切換回來。

tr 任務暫存器(task register) 是乙個16為的選擇子,作用和ldtr類似,都是用來索引全域性描述符表(gdt)中的一項。所不同的是tr選擇的描述符描述的不再是ldt的段了。tr選擇的描述符描述的乙個任務狀態段(tss:task status segment)。

tss 任務狀態段(task state segment) 正如前面所說,任務狀態段(tss)是在gdt中描述的。任務狀態段是做什麼的呢?任務狀態段就是記憶體中的乙個資料結構。這個結構中儲存著和任務相關的資訊。當發生任務切換的時候會把當前任務用到的暫存器內容(cs eip ds ss...)包括ldt的選擇子等儲存在tss中以便任務切換回來時候繼續使用。

其實除了上述暫存器以外,還有一些不可訪問的隱藏暫存器,這些隱藏暫存器其實是高速緩衝暫存器,可以忽略它的存在。為了降低理解複雜度上面沒有寫出。將在下面部分給出解釋。

selector 選擇子按照用途共有三種(其實就是一種,因為格式完全一樣), 1.tr中的選擇子,用來從gdt中選擇乙個tss的描述符。 2.ldtr中的選擇子,用來從gdt中選擇乙個ldt的描述符。 3.使用者程式中的邏輯位址(虛擬位址,這個位址48位 = 16位選擇子+32位偏移位址)中包含的選擇子。用來選擇程式用到的段在ldt(或者gdt)中的描述符(資料段,**段...)。這個選擇子由編譯或者連線或者作業系統決定的.

三、分頁

線性位址從高到底被分成三個部分高10位b,中間10位c,末12位d。變換過程不再描述(語言描述可能看上去複雜,其實很簡單)。這裡給出乙個變換公式比較明了: 頁基址 = a; 頁基址 = 頁基址 + b * 4;  /* 查一級目錄頁表,在(頁基址+b*4)處取得二級頁表的的基址,這裡等號的意思是查表 */ 頁基址 = 頁基址 + c * 4 ;  /* 查二級目錄頁表,在(頁基址+b*4)處取得物理基址,這裡等號的意思是查表 */ 實體地址 = 物理基址 + d; 為什麼要x4?因為頁表按4位對齊的。頁目錄項後四位不用。順便說下選擇子去gdt/ldt中索引是:描述符位址 = base+selector*8.為什麼要x8?道理類似,gdt/ldt中一項8位元組。

四、80386記憶體管理和任務切換(具體過程)

乙個80386操作系系統中執行兩個使用者任務a和b 具體如下圖:

這個過程沒有畫出包括上門說的不可訪問的隱藏暫存器。實際上,tr,ldtr之後都有乙個64位(內容和描述符一樣)外部不可訪問的高速緩衝暫存器。內容為當前選擇子對應的描述符。這樣只有在切換任務的時候才去記憶體中gdt索引。具體任務在執行**或者資料定址時cpu直接讀取高速緩衝暫存器中儲存的某個和tr或者ldtr相對應的描述符。

任務a執行

任務b執行

80386保護模式儲存器定址(1)

邏輯位址 logical address 包含在機器語言指令中用來指定乙個運算元或一條指令的位址。每乙個邏輯位址都由乙個段和乙個偏移量組成,偏移量指明了從段的開始到實際位址之間的距離。線性位址 linear address 是乙個 32位無符號整數,可以用來表示高達 4gb的位址。實體地址 p hy...

進入保護模式總結

1.最主要的就是那個jmp dword,一切都是為了jmp做準備 2.int 13h讀取扇區,既可以讀硬碟,又可以讀軟盤,應該是兩個的驅動器號不同 這個還沒搞清楚,現在只會讀軟盤 用硬碟映像的時候,總是說找不到引導裝置,不知道是哪兒的引數錯了。一些細節 cl是讀取的扇區號,1就是第1個扇區,並不是從...

進入保護模式

本文為 每個描述符佔8位元組,下圖中,上面位高32位,下面為低32位 disk boot ata channel 0 first hd cd on channel 0 type of disk image這個選項是vpc,我用2.6.2配置時選vpc無法啟動,得選flat才可以,2.6.0貌似選vp...