歡迎回到標題為“模擬Linus Torvalds”的系列文章。 今天我們將看到GDT。 首先,我們必須了解GDT是什麼。 根據維基百科:
全局描述符表 or GDT 是由 Intel英特爾 x86-系列處理器以 80286 為了定義程序執行期間使用的各種存儲區的特性,包括基地址,大小和訪問特權(如可執行性和可寫性)
轉換後的將是全局描述符表,該數據表是86以來在Intel x80286處理器中使用的數據結構,用於定義程序執行期間使用的各種內存區域的特徵。
總而言之,如果我們使用的是Intel x86處理器,則必須定義GDT以正確使用內存。 我們不會做太多複雜的事情,我們將在表中定義3個條目:
- 所有表都需要一個NULL條目。
- 該部分的票 數據,我們將使用最大值,即32位為4 GB。
- 該部分的票 碼,我們將使用最大值,即32位為4 GB。
如您所見,數據和代碼將使用相同的空間。 好的,現在我們要實現它。 為此,我們將使用兩種結構,第一種將負責包含指向GDT實際數據的指針。 第二個將是包含GDT條目的數組。 讓我們先定義它們
struct Entry{
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t granularity;
uint8_t base_high;
} __attribute__((packed));
struct Ptr{
uint16_t limit;
uint32_t base;
} __attribute__((packed));
您可能已經註意到結構末尾有一個奇怪的__attribute __((包裝))。 這告訴GCC不要優化結構,因為我們想要的是將數據原樣傳遞給處理器。 現在,我們要製作一個功能來安裝GDT。 在我們應該聲明結構之前,現在我們將對其進行初始化。
struct ND::GDT::Entry gdt[3];
struct ND::GDT::Ptr gp;
void ND::GDT::Install()
{
gp.limit=(sizeof(struct ND::GDT::Entry)*3)-1;
gp.base=(uint32_t)&gdt;
}
這樣我們就可以建立指向3輸入表的指針。
void ND::GDT::SetGate(int num, uint32_t base, uint32_t limit, uint8_t access,uint8_t gran)
{
gdt[num].base_low=(base & 0xFFFF);
gdt[num].base_middle=(base >> 16) & 0xFF;
gdt[num].base_high=(base >> 24) & 0xFF;
gdt[num].limit_low=(limit & 0xFFFF);
gdt[num].granularity=(limit >> 16) & 0x0F;
gdt[num].granularity |= (gran & 0xF0);
gdt[num].access=access;
}
我們從安裝函數中調用了3次
ND::GDT::SetGate(0,0,0,0,0); /* NULL segmente entry */
ND::GDT::SetGate(1,0,0xFFFFFFFF,0x9A,0xCF); /* 4 GiB for Code Segment */
ND::GDT::SetGate(2,0,0xFFFFFFFF,0x92,0xCF); /* 4 GiB for Data segment */
最後,我們必須告訴處理器我們有一個GDT,以便可以加載它,並且在我們的情況下,當使用GRUB加載內核時,請覆蓋GRUB GDT。 要加載GDT,在asm中有一條稱為lgdt(或lgdtl,具體取決於語法)的指令,我們將使用它。
asm volatile("lgdtl (gp)");
asm volatile(
"movw $0x10, %ax \n"
"movw %ax, %ds \n"
"movw %ax, %es \n"
"movw %ax, %fs \n"
"movw %ax, %gs \n"
"movw %ax, %ss \n"
"ljmp $0x08, $next \n"
"next: \n"
);
好了,一旦完成此操作,我們的系統將已經具有GDT。 在下一章中,我們將看到IDT,該表與GDT非常相似,但存在中斷。 我在GDT中添加了一些狀態和確認消息,因此NextDivel現在看起來像這樣:
也許64位結構更適合這些時代,繼續使用8086是一個積壓。
我一直在尋找有關x86_64中GDT的信息,我認為它遵循舊模型並帶有特殊標誌。 仍使用32位地址。 現在我不知道確切如何正確地做。 一些鏈接:
http://wiki.osdev.org/Entering_Long_Mode_Directly
http://f.osdev.org/viewtopic.php?f=1&t=16275
首先,您的貢獻非常好,但我認為標題應該是
“模仿理查德·斯托曼”,或者至少我是這樣認為的,
問候
Linus創建了Linux內核,Stallman創建了GNU,這是Unix的工具和命令。
標題是適當的,因為您正在創建一個核。
您好!
非常感謝您回答我的所有問題並耐心等待,作為一個彙編程序,我只了解基礎知識,而作為C幾乎不了解,但是我非常喜歡它,現在我對GDT有點困惑,讓我們看看是否理解。
GDT將具有可始終由任何程序訪問的全局“描述符”,並且這些描述符指向將要執行(程序)的部分? 否則就是這樣。