x86記憶體定址

2021-06-19 06:39:02 字數 3388 閱讀 6868

最近又研究了一下記憶體定址,沒有乙份資料能講的透徹,不是不細緻,而是缺乏整體感,都不全面,讓人看完後沒有乙個整體模型,現就我關心的問題記錄如下,如果要很全面很細緻的記錄的話會花費我很多精力,所以只是記錄大概流程,以後再慢慢修正吧。

所有貼圖皆來自網路

一.分段的由來

1.8086

分段的產生主要是因為 8086 處理器,不了解的可以去查一下資料。因為 8086 有 20 根位址線,能訪問 2 的 20 次方共 1mb 的位址空間,但是其暫存器確是 16 位 , 無法儲存 20 位的位址。這時就將 20 位位址分為兩部分,一部分是前 16位 , 儲存在 cpu 的段暫存器中 , 剩下的 4 位儲存在通用暫存器中,這樣就形成了所謂的段位址 : 偏移位址

形式。把 1mb 位址空間分成了 16 份,每份 64kb ,當需要定址時就要把兩部分合併,顯然合併方法就是完整位址 = 段位址 <<4 +偏移位址

, 那麼左移四位就相當於乘以 16.

這裡需要注意 :

理論上每段是 64kb ,但實際偏移位址是 16 位,故其偏移有可能超出本段的範圍,那麼實際上 8086 是允許這樣的,這樣不同的位址可以有不同的段位址 : 偏移位址

的組合方法,亦即兩個段可以覆蓋同一區域。這裡加完之後的 20 位位址即為實體地址。

2.80386

1)實模式

cpu 剛加電或復位時便進入實模式,此模式下工作方式同 8086 基本一致,同樣是只能訪問 1mb 位址空間,並且分段。

2)保護模式

實模式初始化完成後便進入保護模式,此模式下便有了虛擬位址(邏輯位址)、線性位址、實體地址的區分。

邏輯位址,即為程式**中使用的位址,分為段基址和段內偏移位址,但其合成方法有別於 8086 ,不再是簡單的加法,而要複雜得多,就是通過所謂段描述符的機構進行轉換。

線性位址,即邏輯位址轉換完成後形成的乙個 32 位的位址 ,注意 8086 中此處是 20 位, 8086 中線性位址即為實體地址,但此處不一定是,還有分頁機制。

實體地址,真正的物理記憶體的位址,要得到他可真不容易。

二.段描述符表

1.gdt

、ldt

和idt

定義描述符表有三種 , 分別為全域性描述符表 gdt 、區域性描述符表 ldt 和中斷描述符表 idt 。

這三個表是在記憶體中 由作業系統或系統程式設計師所建,並不是固化在**,所以從理論上是可以被讀寫的。這三個表都是描述符**。描述符表是由若干個描述符組成 ,個描述符占用8 個位元組的記憶體空間,每個描述符表內最多可以有8129個描述符。描述符是描述乙個段的大小,位址及各種狀態的

1.

全域性描述符表

gdt:

全域性描述符表在系統中只能有乙個 , 且可以被每乙個任務所共享 . 大部分描述符都可以放在 gdt 中,能被多個任務共享的記憶體區就是通過 gdt 完成的 ,

2.

區域性描述符表

ldt:

區域性描述符表在系統中可以有多個 ,通常情況下是與任務的數量保持對等, 但任務可以沒有區域性描述符表 . 任務間不相干的部分也是通過 ldt 實現的 . 這裡涉及到位址對映的問題 . 和 gdt 一樣 , 中斷門和陷阱門放在 ldt 中是不會起作用的 .

3.

中斷描述符表

idt:

和 gdt 一樣 , 中斷描述符表在系統最多只能有乙個 , 中斷描述符表內可以存放

256個描述符 , 分別對應 256 個中斷 . 因為每個描述符占用 8 個位元組 , 所以 idt 的長度可達 2k. 中斷描述符表中可以有任務門、中斷門、陷阱門三個門描述符 ,其它的描述符在中斷描述符表中無意義。

4.

gdtr

暫存器gdtr 是乙個長度為 48bit 的暫存器,內容為乙個 32 位的基位址和乙個 16 位的段限。其中 32 位的基址是指 gdt 在記憶體中的位址。由系統設定初始化時設定,之後不會改變。

5.

ldtr

暫存器ldtr 是區域性描述符暫存器,由乙個可見的 16 位暫存器(段選擇子)和乙個不可見的描述符暫存器組成(描述符暫存器實際上是乙個不可見的高速緩衝區)。

注意 gdtr 和 ldtr 有區別,原因是每個 ldt 都在 gdt 中存在索引,所以 ldtr 有個段選擇符,用來記錄當前 ldt 在 gdt 中的索引位置,任務切換時,先將新任務的 ldt 在 gdt 中的索引存入 ldtr 的段選擇符,然後再把相應的描述符內容載入到 ldtr 的段描述符暫存器,這樣此任務以後的指令就不需要再次查詢 gdt 表了。

2.ldt

、tss

和gdt

的關係每個任務都有自己 ldt 和 tss ,這是確定的,但是所有任務的 ldt 表和 tss 和 gdt 的關係是什麼?

任務切換

在這裡還要引入乙個段選擇子的概念。段選擇子是乙個段暫存器 ,高

13位用來指示描述符在描述符表中的索引號 ,低兩位是表示使用描述符的特權級別;另外一位( t1 )是 gdt 和 ldt 的訊號量,如果 t1=0 ,則使用 gdtr ,如果 t1=1 ,則使用 ldtr 。

系統中的段暫存器共有六個: cs 、 ss 、 ds 、 es 、 fs 和 gs 。每個段暫存器都有其相應的乙個隱藏描述符暫存器,用來儲存此暫存器所選段的段描述符。當選擇子被裝入段暫存器時,微處理器會自動將其對應的描述符裝入描述符暫存器。

系統任務切換時, ldt 切換,而 gdt 不切換(因為真個系統只有乙個 gdt ),這時新任務的 ldt 描述符的選擇子就被裝入到 ldtr 中。然後根據其索引號在 gdt 表中查詢到相應的 ldt 描述符項,把此描述符的內容載入到 ldtr 的段描述符暫存器中,這樣下次就不用查詢 gdt 表了。

4.位址對映

大致流程:

a. 檢視段選擇符,如果其中 t1=0 ,說明是查詢 gdt 表,如果 t1=1 ,則查詢 ldt 表。

b. 如果是 gdt ,則從 gdtr 中取出 gdt 表在記憶體中的基位址,然後和段選擇符的索引 index*8 相加,得到描述符項在 gdt 中的位址,然後從此項中取出段基址,再把段基址和偏移量運算得到線性位址。

c. 如果是 ldt ,則從 ldtr 中的描述符暫存器中取出 ldt 表在記憶體中的位址,然後和段選擇符的索引 index*8 相加,得到描述符項在 ldt 中的位址,然後從此項中取出段基址,再把段基址和偏移量運算得到線性位址。

d. 如果不採用分頁機制那麼線性位址就已經是實體地址了。

X86保護模式下的記憶體定址

段選擇器 32位彙編中16位段暫存器 cs ds es ss fs gs 中不再存放段基址,而是段描述符在段描述符表中的索引值,d3 d15位是索引值,d0 d1位是優先順序 rpl 用於特權檢查,d2位是描述符表引用指示位ti,ti 0指示從全域性描述表gdt中讀取描述符,ti 1指示從區域性描述...

Intel80x86記憶體定址

intel80x86記憶體定址 cpu通過分段單元把乙個邏輯位址轉換為線性位址,接著,分頁單元把線性位址轉換為實體地址 從80386開始,intel處理器能執行兩種不同的位址轉換模式,為實模式和保護模式。保留實模式是要與早期的cpu保持相容。下面重點討論保護模式。乙個邏輯位址分為段選擇符和指定段內相...

x86彙編 第二章 定址方式

暫存器定址 暫存器間接定址 變址定址 基址加變址定址 立即定址 直接定址 定址相關的問題 示例 inc ax 運算元存放在cpu暫存器內,暫存器的名字就是它的位址,直接操作對應的暫存器 示例 mov ax,si 運算元存放在記憶體中,需要通過暫存器的值 該值就是運算元的偏移位址ea 間接找到運算元 ...