程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 匯編語言 >> 匯編教程:分段管理機制

匯編教程:分段管理機制

編輯:匯編語言

本文介紹保護方式下的段定義以及由段選擇子及段內偏移構成的二維虛擬地址如何被轉換為一維線性地址。

<一>段定義和虛擬地址到線性地址的轉換

段是實現虛擬地址到線性地址轉換機制的基礎。在保護方式下,每個段由如下三個參數進行定義:段基地址(Base Address)、段界限(Limit)和段屬性(Attributes)。

段基地址規定線性地址空間中段的開始地址。在80386保護方式下,段基地址長32位。因為基地址長度與尋址地址的長度相同,所以任何一個段都可以從32位線性地址空間中的任何一個字節開始,而不象實方式下規定的邊界必須被16整除。

段界限規定段的大小。在80386保護模式下,段界限用20位表示,而且段界限可以是以字節為單位或以4K字節為單位。段屬性中有一位對此進行定義,把該位成為粒度位,用符號G標記。G=0表示段界限以字節位位單位,於是20位的界限可表示的范圍是1字節至1M字節,增量為1字節;G=1表示段界限以4K字節為單位,於是20位的界限可表示的范圍是4K字節至4G字節,增量為4K字節。當段界限以4K字節為單位時,實際的段界限LIMIT可通過下面的公式從20 位段界限Limit計算出來:

LIMIT=limit*4K+0FFFH=(Limit SHL 12)+0FFFH

所以當粒度為1時,段的界限實際上就擴展成32位。由此可見,在80386保護模式下,段的長度可大大超過64K字節。

基地址和界限定義了段所映射的線性地址的范圍。基地址Base是線性地址對應於段內偏移為 0的虛擬地址,段內偏移為X的虛擬地址對應Base+X的線性地址。段內從偏移0到Limit范圍內的虛擬地址對應於從Base到Base+Limit范圍內的線性地址。

下圖表示一個段如何從虛擬地址空間定位到線性地址空間。圖中BaseA等代表段基地址, LimitA等代表段界限。另外,段C接在段A之後,也即BaseC=BaseA+LimitA。
  例如:設段A的基地址等於00012345H,段界限等於5678H,並且段界限以字節為單位(G=0),那麼段A對應線性地址空間中從00012345H-000179BDH的區域。如果段界限以4K字節為單位 (G=1),那麼段A對應線性地址空間中從00012345H-0568B344H(=00012345H+5678000H+0FFFH) 的區域。

通過增加段界限,可以使段的容量得到擴展。這對於那些要在內存中擴展容量的普通數據段很有效,但對堆棧段情況就不是這樣。因為堆棧底在高地址端,隨著壓棧操作的進行,堆棧向低地址方向擴展。為了適應普通數據段和堆棧數據段在兩個相反方向上的擴展,數據段的段屬性中安排了一個擴展方向位,標記為ED。ED=0表示向高端擴展,ED=1表示向低端擴展。一般只有堆棧數據段才使用向低端擴展的屬性(堆棧段也可使用向上擴展的段),這是因為,向下擴展的段是為以下兩個目的而設計的:

第一,堆棧段被定義為獨特段,即DS和SS包含不同的選擇器。

第二,一個堆棧段是靠將它復制到一個更大的段來擴充自己(而不是靠將現存的頁增加到它的段上)。不打算用這種方法實現堆棧的設計者不需要定義向下擴展的段。

需要注意的是,只有數據段的段屬性中才有擴展方向屬性位ED,也就是說只有數據段(堆棧段作為特殊的數據段)才有向上擴展和向下擴展之分,其它段都是自然的向上擴展。

數據段的擴展方向和段界限一起決定了數據段內偏移的有效范圍。當段最大為1M字節時,在向高端擴展的段內,從0到Limit的偏移是合法有效的偏移,而從Limit+1到1M-1的偏移是非法無效的偏移;在向低端擴展的段內,情形剛好相反,從0到Limit的偏移是非法無效的偏移,而從Limit+1到1M-1的偏移是合法有效的偏移,注意邊界值Limit對應地址的有效性。段最大為4G時,情形類似。由此可見,如果一個段是向下擴展的,則所有的偏移必須大於限長,因為其限長是指下限,其基地址從高地址出開始。反之,若一個段是向上擴展的,則所有偏移必須小於等於限長,因為其限長是指上限,基地址從低地址處開始。通過使用段環繞,可以把向下擴展段定義到任何線性地址且可定義為任何大小。

在每次把虛擬地址轉換為線性地址的過程中,要對偏移進行檢查。如果偏移不在有效的范圍內,那麼就引起異常。

段屬性規定段的主要特性。例如上面已經提到的段粒度G就是段屬性的一部分。在對段進行各種訪問時,將對訪問是否合法進行檢查,主要依據是段屬性。例如:如果向一個只讀段進行寫入操作,那麼不僅不能寫入,而且會引起異常。在下面會詳細說明各個段熟屬性位的定義和作用。

<二>存儲段描述符

用於表示上述定義段的三個參數的數據結構稱為描述符。每個描述符長8個字節。在保護方式下,每一個段都有一個相應的描述符來描述。按描述符所描述的對象來劃分,描述符可分為如下三類:存儲段描述符、系統段描述符、門描述符(控制描述符)。下面先介紹存儲段描述符。

1.存儲段描述符的格式

存儲段是存放可由程序直接進行訪問的代碼和數據的段。存儲段描述符描述存儲段,所以存儲段描述符也被稱為代碼和數據段描述符。存儲段描述符的格式如下表所示。表中上面一排是對描述符8個字節的使用的說明,最低地址字節(假設地址為m)在最右邊,其余字節依次向左,直到最高字節(地址為m+7)。下一排是對屬性域各位的說明。

存儲段

描述符

m+7 m+6 m+5 m+4 m+3 m+2 m+1 m+0 Base(31...24) Attributes Segment Base(23...0) Segment Limite(15...0)

存儲段

描述符

屬 性

Byte m+6 Byte m+5 BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 G D 0 AVL Limit(19...16) P DPL DT1 TYPE

從上表可知,長32位的段基地址(段開始地址)被安排在描述符的兩個域中,其位0—位23 安排在描述符內的第2—第4字節中,其位24—位31被安排在描述符內的第7字節中。長20 位的段界限也被安排在描述符的兩個域中,其位0—位15被安排在描述符內的第0—第1字節中,其位16—位19被安排在描述符內的第6字節的低4位中。

使用兩個域存放段基地址和段界限的原因與80286有關。在80286保護方式下,段基地址只有24位長,而段界限只有16位長。80286存儲段描述符盡管也是8字節長,但實際只使用低 6字節,高2字節必須置為0。80386存儲段描述符這樣的安排,可使得80286的存儲段描述符的格式在80386下繼續有效。

80386描述符中的段屬性也被安排在兩個域中。下面對其定義及意義作說明。

(1)P位稱為存在(Present)位。P=1表示描述符對地址轉換是有效的,或者說該描述符所描述的段存在,即在內存中;P=0表示描述符對地址轉換無效,即該段不存在。使用該描述符進行內存訪問時會引起異常。

(2)DPL表示描述符特權級(Descriptor Privilege level),共2位。它規定了所描述段的特權級,用於特權檢查,以決定對該段能否訪問。

(3)DT位說明描述符的類型。對於存儲段描述符而言,DT=1,以區別與系統段描述符和門描述符(DT=0)。

(4)TYPE說明存儲段描述符所描述的存儲段的具體屬性。

其中的位0指示描述符是否被訪問過(Accessed),用符號A標記。A=0表示尚未被訪問,A=1 表示段已被訪問。當把描述符的相應選擇子裝入到段寄存器時,80386把該位置為1,表明描述符已被訪問。操作系統可測試訪問位,已確定描述符是否被訪問過。

其中的位3指示所描述的段是代碼段還是數據段,用符號E標記。E=0表示段為數據段,相應的描述符也就是數據段(包括堆棧段)描述符。數據段是不可執行的,但總是可讀的。 E=1表示段是可執行段,即代碼段,相應的描述符就是代碼段描述符。代碼段總是不可寫的,若需要對代碼段進行寫入操作,則必須使用別名技術,即用一個可寫的數據段描述符來描述該代碼段,然後對此數據段進行寫入。

在數據段描述符中(E=0的情況),TYPE中的位1指示所描述的數據段是否可寫,用W標記。 W=0表示對應的數據段不可寫。反之,W=1表示數據段是可寫的。注意,數據段總是可讀的。TYPE中的位2是ED位,指示所描述的數據段的擴展方向。ED=0表示數據段向高端擴展,也即段內偏移必須小於等於段界限。ED=1表示數據段向低擴展,段內偏移必須大於段界限。

在代碼段描述符中(E=1的情況),TYPE中的位1指示所描述的代碼段是否可讀,用符號R標記。R=0表示對應的代碼段不可讀,只能執行。R=1表示對應的代碼段可讀可執行。注意代碼段總是不可寫的,若需要對代碼段進行寫入操作,則必須使用別名技術。在代碼段中,TYPE中的位2指示所描述的代碼段是否是一致代碼段,用C標記。C=0表示對應的代碼段不是一致代碼段(普通代碼段),C=1表示對應的代碼段是一致代碼段。關於一致代碼段的說明,後面的文章將會詳細介紹。

存儲段描述符中的TYPE字段所說明的屬性可歸納為下表:

數據段

類 型

類型值 說   明 0 只讀 1 只讀、已訪問 2 讀/寫 3 讀/寫、已訪問 4 只讀、向下擴展 5 只讀、向下擴展、已訪問 6 讀/寫、向下擴展 7 讀/寫、向下擴展、已訪問 代碼段

類 型

類型值 說   明 8 只執行 9 只執行、已訪問 A 執行/讀 B 執行/讀、已訪問 C 只執行、一致碼段 D 只執行、一致碼段、已訪問 E 執行/讀、一致碼段 F 執行/讀、一致碼段、已訪問

(5)G為就是段界限粒度(Granularity)位。G=0表示界限粒度為字節;G=1表示界限粒度為4K 字節。注意,界限粒度只對段界限有效,對段基地址無效,段基地址總是以字節為單位。

(6)D位是一個很特殊的位,在描述可執行段、向下擴展數據段或由SS寄存器尋址的段(通常是堆棧段)的三種描述符中的意義各不相同。

在描述可執行段的描述符中,D位決定了指令使用的地址及操作數所默認的大小。D=1表示默認情況下指令使用32位地址及32位或8位操作數,這樣的代碼段也稱為32位代碼段;D=0 表示默認情況下,使用16位地址及16位或8位操作數,這樣的代碼段也稱為16位代碼段,它與80286兼容。可以使用地址大小前綴和操作數大小前綴分別改變默認的地址或操作數的大小。

在向下擴展數據段的描述符中,D位決定段的上部邊界。D=1表示段的上部界限為4G;D=0表示段的上部界限為64K,這是為了與80286兼容。

在描述由SS寄存器尋址的段描述符中,D位決定隱式的堆棧訪問指令(如PUSH和POP指令)使用何種堆棧指針寄存器。D=1表示使用32位堆棧指針寄存器ESP;D=0表示使用16位堆棧指針寄存器SP,這與80286兼容。

(7)AVL位是軟件可利用位。80386對該位的使用未左規定,Intel公司也保證今後開發生產的處理器只要與80386兼容,就不會對該位的使用做任何定義或規定。

此外,描述符內第6字節中的位5必須置為0,可以理解成是為以後的處理器保留的。

2.存儲段描述符的結構類型表示

根據存儲段描述符的結構,可定義如下的匯編語言描述符結構類型:

DESC STRUC

LIMITL DW 0 ;段界限低16位

BASEL DW 0 ;基地址低16位

BASEM DB 0 ;基地址中間8位

ATTRIB DB 0 ;段屬性

LIMITH DB 0 ;段界限的高4位(包括段屬性的高4位)

BASEH DB 0 ;基地址的高8位

DESC ENDS

利用結構類型DESC能方便地在程序中說明存儲段描述符。例如:下面的描述符DATAS描述一個可讀寫的有效(存在的)數據段,基地址是100000H,以字節為單位的界限是0FFFFH,描述符特權級DPL=3。

DATAS DESC < 0FFFFH ,, 10H , 0F2H ,,>

再如:下述描述符CODEA描述一個只可執行的有效的32位代碼段,基地址是12345678H,以 4K字節位單位的段界限值是10H(以字節位單位的界限是10FFFH),描述符特權級DPL=0。

CODEA DESC < 10H , 5678H , 34H , 98H , 0C0H , 12H >

<三>全局和局部描述符表

一個任務會涉及多個段,每個任務需要一個描述符來描述,為了便於組織管理,80386把描述符組織成線性表。由描述符組成的線性表稱為描述符表。在80386中有三種類型的描述符表:全局描述符表GDT(Global Descriptor Table)、局部描述符表LDT(Local Descriptor Table)和中斷描述符表IDT(Interrupt Descriptor Table)。在整個系統中,全局描述符表GDT和中斷描述符表IDT只有一張,局部描述符表可以有若干張,每個任務可以有一張。

例如,下列描述符表有6個描述符構成:

DESCTAB LABEL BYTE

DESC1 DESC <1234H,5678H,34H,92H,,>

DESC1 DESC <1234H,5678H,34H,93H,,>

DESC1 DESC <5678H,1234H,56H,98H,,>

DESC1 DESC <5678H,1234H,56H,99H,,>

DESC1 DESC <0FFFFH,,10H,16H,,>

DESC1 DESC <0FFFFH,,10H,90H,,>

每個描述符表本身形成一個特殊的數據段。這樣的特殊數據段最多可包含有8K(8192)個描述符.

關於中斷描述符表IDT在以後的文章中介紹。

每個任務的局部描述符表LDT含有該任務自己的代碼段、數據段和堆棧段的描述符,也包含該任務所使用的一些門描述符,如任務門和調用門描述符等。隨著任務的切換,系統當前的局部描述符表LDT也隨之切換。(本文來自編程入門網:www.bianceng.cn)

全局描述符表GDT含有每一個任務都可能或可以訪問的段的描述符,通常包含描述操作系統所使用的代碼段、數據段和堆棧段的描述符,也包含多種特殊數據段描述符,如各個用於描述任務LDT的特殊數據段等。在任務切換時,並不切換GDT。

通過LDT可以使各個任務私有的各個段與其它任務相隔離,從而達到受保護的目的。通過GDT可以使各任務都需要使用的段能夠被共享。下圖給出了任務A和任務B所涉及的有關段既隔離受保護,又合用共享的情況。通過任務A的局部描述符表LDTA和任務B的局部描述符表LDTB,把任務A所私有的代碼段CodeA及數據段DataA與任務B所私有的代碼段CodeB和數據段DataB及DataB2隔離,但任務A和任務B通過全局描述符表GDT共享代碼段CodeK及CodeOS和數據段DataK及DataOS。
  一個任務可使用的整個虛擬地址空間分為相等的兩半,一半空間的描述符在全局描述符表中,另一半空間的描述符在局部描述符表中。由於全局和局部描述符表都可以包含多達8192個描述符,而每個描述符所描述的段的最大值可達4G字節,因此最大的虛擬地址空間可為:

4GB*8192*2=64MMB=64TB

<四>段選擇子

在實模式下,邏輯地址空間中存儲單元的地址由段值和段內偏移兩部分組成。在保護方式下,虛擬地址空間(相當於邏輯地址空間)中存儲單元的地址由段選擇子和段內偏移兩部分組成。與實模式相比,段選擇子代替了段值。

段選擇子長16位,其格式如下表所示。從表中可見,段選擇子的高13位是描述符索引(Index)。所謂描述符索引是指描述符在描述符表中的序號。段選擇子的第2位是引用描述符表指示位,標記為TI(Table Indicator),TI=0指示從全局描述符表GDT中讀取描述符;TI=1指示從局部描述符表LDT中讀取描述符。

選擇子

結 構

BIT15 BIT14 BIT13 BIT12 BIT11 BIT10 BIT9 BIT8 BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0 描述符索引 TI RPL

選擇子確定描述符,描述符確定段基地址,段基地址與偏移之和就是線性地址。所以,虛擬地址空間中的由選擇子和偏移兩部分構成的二維虛擬地址,就是這樣確定了線性地址空間中的一維線性地址。

選擇子的最低兩位是請求特權級RPL(Requested Privilege Level),用於特權檢查。 RPL字段的用法如下:

每當程序試圖訪問一個段時,要把當前特權級與所訪問段的特權級進行比較,以確定是否允許程序對該段的訪問。使用選擇子的RPL字段,將改變特權級的測試規則。在這種情況下,與所訪問段的特權級比較的特權級不是CPL,而是CPU與RPL中更外層的特權級。 CPL存放在CS寄存器的RPL字段內,每當一個代碼段選擇子裝入CS寄存器中時,處理器自動地把CPL存放到CS的RPL字段。

由於選擇子中的描述符索引字段用13位表示,所以可區分8192個描述符。這也就是描述符表最多包含8192個描述符的原因。由於每個描述符長8字節,根據上表所示選擇子的格式,屏蔽選擇子低3位後所得的值就是選擇子所指定的描述符在描述符表中的偏移,這可認為是安排選擇子高13位作為描述符索引的原因。

有一個特殊的選擇子稱為空(Null)選擇子,它的Index=0,TI=0,而RPL字段可以為任意值。空選擇子有特定的用途,當用空選擇子進行存儲訪問時會引起異常。空選擇子是特別定義的,它不對應於全局描述符表GDT中的第0個描述符,因此處理器中的第0個描述符總不被處理器訪問,一般把它置成全0。但當TI=1時,Index為0的選擇子不是空選擇子,它指定了當前任務局部描述符表LDT中的第0個描述符。

<五>段描述符高速緩沖寄存器

在實模式下,段寄存器含有段值,為訪問存儲器形成物理地址時,處理器引用相應的某個段寄存器並將其值乘以16,形成20位的段基地址。在保護模式下,段寄存器含有段選擇子,如上所述,為了訪問存儲器形成線性地址時,處理器要使用選擇子所指定的描述符中的基地址等信息。為了避免在每次存儲器訪問時,都要訪問描述符表而獲得對應的段描述符,從80286開始每個段寄存器都配有一個高速緩沖寄存器,稱之為段描述符高速緩沖寄存器或描述符投影寄存器,對程序員而言它是不可見的。每當把一個選擇子裝入到某個段寄存器時,處理器自動從描述符表中取出相應的描述符,把描述符中的信息保存到對應的高速緩沖寄存器中。此後對該段訪問時,處理器都使用對應高速緩沖寄存器中的描述符信息,而不用再從描述符表中取描述符。

各段描述符高速緩沖寄存器之內容如下表所示。其中,32位段基地址直接取自描述符, 32位的段界限取自描述符中20位的段界限,並根據描述符屬性中的粒度位轉換成以字節為單位。其它十個特性根據描述符中的屬性而定,“Y”表示“是”,“N”表示“否” ,“R”表示必須可讀,“W”表示必須可寫,“P”表示必須存在,“D”表示根據描述符中屬性而定。

段描

述符

高速

緩沖

寄存

器的

內容

段寄存器 段基地址 段界限 段屬性 存在性 特權級 已存取 粒度 擴展方向 可讀性 可寫性 可執行 堆棧大小 一致特權 CS 32位基地址 32位段界限 P D D D D D N Y - D SS 32位基地址 32位段界限 P D D D D R W N D - DS 32位基地址 32位段界限 P D D D D D D N - - ES 32位基地址 32位段界限 P D D D D D D N - - FS 32位基地址 32位段界限 P D D D D D D N - - GS 32位基地址 32位段界限 P D D D D D D N - -

段描述符高速緩沖寄存器再處理器內,所以可對其進行快速訪問。絕大多數情況下,對存儲器的訪問是在對應選擇子裝入到段寄存器之後進行的,所以,使用段描述符高速緩沖寄存器可以得到很好的執行性能。

段描述符高速緩沖寄存器之內保存的描述符信息將一直保存到重新把選擇子裝載到段寄存器時再更新。程序員盡管不可見段描述符高速緩沖寄存器,但必須注意到它的存在和它的上述更新時機。例如,在改變了描述符表中的某個當前段的描述符後,也要更新對應的段描述符高速緩沖寄存器的內容,即使段選擇子未作改變,這可通過重新裝載段寄存器實現。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved