日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

80386的分段机制、分页机制和物理地址的形成

發布時間:2024/8/5 综合教程 40 生活家
生活随笔 收集整理的這篇文章主要介紹了 80386的分段机制、分页机制和物理地址的形成 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


MOVE REG,ADDR ;
它把地址為ADDR(假設為10000)的內存單元的內容復制到REG 中


在8086 的實模式下,把某一段寄存器(段基址)左移4 位,然后與地址ADDR 相加后被直接送到內
存總線上,這個相加后的地址(20位)就是內存單元的物理地址,而程序中的這個地址ADDR就叫邏輯地址
(或叫虛地址)。


在80386 的段機制中,邏輯地址由兩部分組成,即
段部分(選擇符)
及偏移部分。

段是形成邏輯地址到線性地址轉換的基礎。如果我們把段看成一個對象的話,那么對它
的描述如下。

(1)段的基地址(Base Address):在線性地址空間中段的起始地址。

(2)段的界限(Limit):表示在邏輯地址中,段內可以使用的最大偏移量。

(3)段的屬性(Attribute): 表示段的特性。例如,該段是否可被讀出或寫入,或者
該段是否作為一個程序來執行,以及段的特權級等。


1、邏輯地址、線性地址和物理地址





所謂
描述符(Descriptor)
,就是描述段的屬性的一個8 字節存儲單元。


2、用戶段描述符(Descriptor)




一個段描述符指出了段的32 位基地址和20 位段界限(即段大?。?。
第6 個字節的G 位是粒度位,當G=0 時,段長表示段格式的字節長度,即一個段最長可
達1M 字節。當G=1 時,段長表示段的以4K 字節為一頁的頁的數目,即一個段最長可達
1M×4K=4G 字節。D 位表示缺省操作數的大小,如果D=0,操作數為16 位,如果D=1,操作數
為32 位。


第7 位P 位(Present) 是存在位,表示段描述符描述的這個段是否在內存中,如果在
內存中。P=1;如果不在內存中,P=0。


DPL(Descriptor Privilege Level)
,就是描述符特權級,它占兩位,其值為0~3,
用來確定這個段的特權級即保護等級。0為內核級別,3為用戶級別。


S 位(System)表示這個段是系統段還是用戶段。如果S=0,則為系統段,如果S=1,則
為用戶程序的代碼段、數據段或堆棧段。


類型占3 位,第3 位為E 位,表示段是否可執行。當E=0 時,為數據段描述符,這時的
第2 位ED 表示地址增長方向。
第1 位(W)是可寫位
。
當段為代碼段時,第3 位E=1,這時第2 位為一致位(C)。當C=1 時,如果當前特權級
低于描述符特權級,并且當前特權級保持不變,那么代碼段只能執行。所謂當前特權級
CPL
(Current Privilege Level)
,就是當前正在執行的任務的特權級。第1 位為可讀位R


存取權字節的第0 位A 位是訪問位,用于請求分段不分頁的系統中,每當該段被訪問時,
將A 置1。對于分頁系統,則A 被忽略未用。


3、系統段描述符

系統段描述符的第5 個字節的第4 位為0,說明它是系統段描述符,類型占
4 位,沒有A 位。第6 個字節的第6 位為0,說明系統段的長度是字節粒度,所以,一個系統
段的最大長度為1M 字節。

系統段的類型為16 種,如圖2.15 所示。
在這16 種類型中,保留類型和有關286 的類型不予考慮。
門也是一種描述符,有調用門、任務門、中斷門和陷阱門4 種門描述符
。




4、選擇符、描述符表和描述符表寄存器


描述符表(即段表)定義了386 系統的所有段的情況。所有的描述符表本身都占據一個
字節為8 的倍數的存儲器空間,空間大小在8 個字節(至少含一個描述符)到64K 字節(至
多含8K=8192)個描述符之間。


1.全局描述符表(GDT)

全局描述符表GDT(Global Descriptor Table),除了任務門,中斷門和陷阱門描述符
外,包含著系統中所有任務都共用的那些段的描述符。它的第一個8 字節位置沒有使用。


2.中斷描述符表(IDT)

中斷描述符表IDT(Interrupt Descriptor Table),包含256 個門描述符。IDT 中只
能包含任務門、中斷門和陷阱門描述符,雖然IDT 表最長也可以為64K 字節,但只能存取2K
字節以內的描述符,即256 個描述符,這個數字是為了和8086 保持兼容。


3.局部描述符表(LDT)

局部描述符表LDT(Local Descriptor Table),包含了與一個給定任務有關的描述符,
每個任務各自有一個的LDT。有了LDT,就可以使給定任務的代碼、數據與別的任務相隔離。
每一個任務的局部描述符表LDT 本身也用一個描述符來表示,稱為LDT 描述符,它包含

了有關局部描述符表的信息,被放在全局描述符表GDT 中,使用LDTR進行索引。


在實模式下,段寄存器存儲的是真實的段基址,在保護模式下,16 位的段寄存器無法放
下32 位的段基址,因此,它們被稱為選擇符,即段寄存器的作用是用來選擇描述符。選擇符
的結構如圖2.16 所示。


可以看出,選擇符有3 個域:第15~3 位這13 位是索引域,表示的數據為0~8129,用于
指向全局描述符表中相應的描述符。第2 位為選擇域,如果TI=1,就從局部描述符表中選擇
相應的描述符,如果TI=0,就從全局描述符表中選擇描述符。第1、0 位是特權級,表示選
擇符的特權級,被稱為請求者特權級
RPL(Requestor Privilege Level
)。只有請求者特權
級RPL 高于(數字低于)或等于相應的描述符特權級DPL,描述符才能被存取,這就可以實
現一定程度的保護。


下面講一下在沒有分頁操作時,尋址一個存儲器操作數的步驟。


(1)在段選擇符中裝入16 位數,同時給出32 位地址偏移量(比如在ESI、EDI 中等)。


(2)先根據相應描述符表寄存器中的段地址(
確定描述符表的地址
)和
段界限
(確定描述符表的大?。?br /> ,根據段選擇符的TI決定從哪種描述符表中取,再根據段選擇符的索引找到相應段描述符的位置
,比較RPL與DPL,若該段無問題,就取出相應的段
描述符放入段描述符高速緩沖寄存器中。


(3)將段描述符中的32 位段基地址和放在ESI、EDI 等中的32 位有效地址相加,就形成
了32 位物理地址。



5、linux中的段機制


從2.2 版開始,Linux 讓所有的進程(或叫任務)都使用相同的邏輯地址空間,因此就
沒有必要使用局部描述符表LDT。


Linux 在啟動的過程中設置了段寄存器的值和全局描述符表GDT 的內容,段寄存器的定義在
include/asm-i386/segment.h 中:


C++ Code

1

2

3

4

5

#define__KERNEL_CS0x10
//內核代碼段,index=2,TI=0,RPL=0

#define__KERNEL_DS0x18
//內核數據段,index=3,TI=0,RPL=0

#define__USER_CS0x23
//用戶代碼段,index=4,TI=0,RPL=3

#define__USER_DS0x2B
//用戶數據段,index=5,TI=0,RPL=3


從定義看出,沒有定義堆棧段,實際上,Linux 內核不區分數據段和堆棧段,這也體現
了Linux 內核盡量減少段的使用。因為沒有使用LDT,因此,TI=0,并把這4 個段描述符都放在GDT
中, index 就是某個段描述符在GDT 表中的下標。內核代碼段和數據段具有最高特權,因此其RPL

為0,而用戶代碼段和數據段具有最低特權,因此其RPL 為3。


全局描述符表的定義在arch/i386/kernel/head.S 中:


C++ Code

1

2

3

4

5

6

7

8

9

10

ENTRY(gdt_table)

.quad0x0000000000000000
/*NULLdescriptor*/

.quad0x0000000000000000
/*notused*/

.quad0x00cf9a000000ffff
/*0x10kernel4GBcodeat0x00000000*/

.quad0x00cf92000000ffff
/*0x18kernel4GBdataat0x00000000*/

.quad0x00cffa000000ffff
/*0x23user4GBcodeat0x00000000*/

.quad0x00cff2000000ffff
/*0x2buser4GBdataat0x00000000*/

.quad0x0000000000000000
/*notused*/

.quad0x0000000000000000
/*notused*/


從代碼可以看出,GDT 放在數組變量gdt_table 中。按Intel 規定,GDT 中的第一項為
空,這是為了防止加電后段寄存器未經初始化就進入保護模式而使用GDT 的。第二項也沒用。
從下標2~5 共4 項對應于前面的4 種段描述符值。對照圖2.10,從描述符的數值可以得出:


• 段的基地址全部為0x00000000;

• 段的上限全部為0xffff;

• 段的粒度G 為1,即段長單位為4KB;

• 段的D 位為1,即對這4 個段的訪問都為32 位指令;

• 段的P 位為1,即4 個段都在內存。


由此可以得出,每個段的邏輯地址空間范圍為0~4GB。
每個段的基地址為0,因此,邏輯地
址到線性地址映射保持不變,也就是說,
偏移量就是線性地址
,我們以后所提到的邏輯地址
(或虛擬地址)和線性地址指的也就是同一地址??磥恚琇inux 巧妙地把段機制給繞過去了,
它只把段分為兩種:用戶態(RPL
=3)的段和內核態(RPL=0)的段,
而完全利用了分頁機制。


按Intel 的規定,每個進程有一個任務狀態段(TSS)和局部描述符表LDT,但Linux 也
沒有完全遵循Intel 的設計思路。如前所述,Linux 的進程沒有使用LDT,而對TSS 的使用也
非常有限,每個CPU 僅使用一個TSS。
TSS 有它自己 8 字節的任務段描述符(Task State Segment Descriptor ,簡稱
TSSD)。這個描述符包括指向TSS 起始地址的32 位基地址域,20 位界限域,界限域值不能小
于十進制104(由TSS 段的最小長度決定)。TSS 描述符存放在GDT 中,它是GDT 中的一個表
項,由中斷描述符表(IDT)中的任務門(存放TSS段的選擇符)裝入TR來進行索引。



7、頁目錄項、頁表項、頁面項


80386 使用4K 字節大小的頁。每一頁都有4K 字節長,并在4K 字節的邊界上對齊,即每
一頁的起始地址都能被4K 整除。因此,80386 把4G 字節的線性地址空間,劃分為1G 個頁面,
每頁有4K 字節大小。分頁機制通過把線性地址空間中的頁,重新定位到物理地址空間來進行
管理,因為每個頁面的整個4K 字節作為一個單位進行映射,并且每個頁面都對齊4K 字節的
邊界,因此,線性地址的低12 位經過分頁機制直接地作為物理地址的低12 位使用。


頁目錄表
,
存儲在一個4K 字節的頁面中,
最多可包含1024 個
頁目錄項
,每個頁目錄項為4 個字節,結
構如圖2.22 所示。




第31~12 位是20 位頁表地址,由于頁表地址的低12 位總為0,所以用高20 位指出
32 位頁表地址就可以了。


第0 位是存在位,如果P=1,表示頁表地址指向的該頁在內存中,如果P=0,表示不
在內存中。



第1 位是讀/寫位,第2 位是用戶/管理員位,這兩位為頁目錄項提供硬件保護。當特
權級為3 的進程要想訪問頁面時,需要通過頁保護檢查,而特權級為0 的進程就可以繞過頁
保護,如圖2.23 所示。



第3 位是PWT(Page Write-Through)位,表示是否采用寫透方式,寫透方式就是既
寫內存(RAM)也寫高速緩存,該位為1 表示采用寫透方式。
第4 位是PCD(Page Cache Disable)位,表示是否啟用高速緩存,該位為1 表示啟
用高速緩存。



第5 位是訪問位,當對頁目錄項進行訪問時,A 位=1。


第7 位是Page Size 標志,只適用于頁目錄項。如果置為1,頁目錄項指的是4MB 的
頁面,即擴展分頁。


80386 的每個頁目錄項指向一個
頁表
,
存儲在一個4K 字節的頁面中,
頁表最多含有1024 個
頁面項
,每項4 個字節,包
含頁面的起始地址和有關該頁面的信息。頁面的起始地址也是4K 的整數倍,所以頁面的低
12 位也留作它用,如圖2.24 所示。



第31~12 位是
20 位物理頁面地址
,除第6 位外第0~5 位及9~11 位的用途和頁目錄
項一樣,第6 位是頁面項獨有的,當對涉及的頁面進行寫操作時,D 位被置1。

4GB 的存儲器只有一個頁目錄,它最多有1024 個頁目錄項,每個頁目錄項又含有1024
個頁面項,因此,存儲器一共可以分成1024×1024=1M 個頁面。由于每個頁面為4K 個字節,
所以,存儲器的大小正好最多為4GB。


當訪問一個操作單元時,如何由分段結構確定的32 位線性地址通過分頁操作轉化成32
位物理地址呢?


第一步,CR3 包含著頁目錄的起始地址,用32 位線性地址的最高10 位A31~A22 作為頁
目錄表的頁目錄項的索引,將它乘以4,與CR3 中的頁目錄表的起始地址相加,形成相應頁目錄項的
地址。


第二步,從指定的地址中取出32 位頁目錄項,它的低12 位為0,這32 位是頁表的起始
地址。用32 位線性地址中的A21~A12 位作為頁表中的頁表項的索引,將它乘以4,與頁表的起
始地址相加,形成相應頁表項的地址。


第三步,從指定地址中取出32位頁表項,它的低12位為0,這32位是頁面地址,將A11~A0 作為相對于頁面地址的偏移量,與32 位頁面地址相加,形成32 位
物理地址。




8、linux 中的分頁機制


Linux 的分段機制使得所有的進程都使用相同的段寄存器值,這就使得內存管理變得
簡單,也就是說,所有的進程都使用同樣的線性地址空間(0~4GB)。
Linux 采用三級分頁模式而不是兩級
。如圖2.28 所示為三級分頁模式,為此,Linux
定義了3 種類型的表。


• 總目錄PGD(Page Global Directory)

• 中間目錄PMD(Page Middle Derectory)

• 頁表PT(Page Table)




總結

以上是生活随笔為你收集整理的80386的分段机制、分页机制和物理地址的形成的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。