全域性描述符表 GDT
全域性描述符表GDT
全域性描述符表主要是為了讓計算機從真實模式到保護模式.
在真實模式下面訪問的地址都是真實的實體地址, 這樣的話每個程式都能直接的訪問實體地址, 並修改實體地址會很容易的造成系統的崩潰, 宕機. 所以為了讓使用者不能直接的訪問實體地址創造了虛擬地址, 而讓系統從實體地址對映到邏輯地址就是從真實模式到保護模式的過程.(這裡的實體地址就是線性地址, 主要因為只分段那麼 實體地址=線性地址, 這裡我就說是實體地址到邏輯地址之間的對映)
邏輯地址採用的分段的策略. 而讓邏輯地址長度遠多大於了實體地址的長度, 邏輯地址的由兩段組成
[段選擇(段選擇子) : 段描述符]
[16位 : 32位]
每段選擇是由16位組成, 段描述符是由32位組成, 由段選擇子確定要訪問哪個段描述符. 一個段描述符對應著一個程序, 也就是一個程序有一個唯一的段選擇子對應. 段描述符有32位, 也就擁有2^32個地址, 也就是4G的地址範圍啊, 正好是一個程序的執行記憶體的大小, 但是要注意不是程序一建立就會分配4G的記憶體, 不然我們電腦記憶體在大也執行不了幾個程序, 程序的4G記憶體都是虛擬記憶體, 實際分配的大小是很小的, 直到程序認為自己的記憶體不足的時候才再申請更大的記憶體而已.
段選擇和段描述符一共是48位的大小, 我們的暫存器根本沒有這個位的, 怎麼儲存? 實際上GDT單獨存放在GDTR特殊暫存器中, 低16位儲存GDT大小, 高32位儲存GDT在儲存器中的位置. 它的結構體可設定為
typedef struct gdt_ptr_t
{
uint16_t limit;
uint32_t base;
}__attribute__((packed)) gdt_ptr_t;
GDT
表包含段描述符, 每個段32位(8個位元組). 裡面同時包含了段的訪問許可權. 所以是以4k進行對齊, 所以低3位都是為0, 而在分頁機制中許可權的判斷就是在頁的低3位進行判斷., 可讀寫還是執行以及訪問許可權.
在NASM語法中每個GDT的資訊的在另個結構體中儲存
typedef struct gdt_entry_struct
{
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t granularity;
uint8_t base_high;
}__attribute__((packed)) gpt_entry_struct;
GDT可以在記憶體的任何位置存放. 但是系統從真實模式進入保護模式之前系統就應該要先為GDT分配記憶體, 而真實模式是在1M一下的記憶體執行的, 那麼GDT最初初始化並分配也就應該是在1M的空間中, 當開啟保護模式後就可以在保護模式的地址空間內重新申請記憶體.
關於邏輯地址和線性地址以及GDT想了解的可以看一下我的另一篇部落格地址空間