模擬Linus Torvalds:從頭開始創建自己的操作系統(IV)

歡迎回到標題為“模擬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輸入表的指針。

如果使用64位進行編譯,則很有可能在此處失敗。 這是因為64位系統上的指針顯然是64位的,這裡我們使用32位類型。 使用-m32選項可能現在有所幫助
現在我們定義一個通用函數將數據放入輸入中

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現在看起來像這樣:

NextDivel-GDT


發表您的評論

您的電子郵件地址將不會被發表。 必填字段標有 *

*

*

  1. 負責數據:MiguelÁngelGatón
  2. 數據用途:控制垃圾郵件,註釋管理。
  3. 合法性:您的同意
  4. 數據通訊:除非有法律義務,否則不會將數據傳達給第三方。
  5. 數據存儲:Occentus Networks(EU)託管的數據庫
  6. 權利:您可以隨時限制,恢復和刪除您的信息。

  1.   賽隆 他說:

    也許64位結構更適合這些時代,繼續使用8086是一個積壓。

    1.    阿德里安·阿羅約街 他說:

      我一直在尋找有關x86_64中GDT的信息,我認為它遵循舊模型並帶有特殊標誌。 仍使用32位地址。 現在我不知道確切如何正確地做。 一些鏈接:
      http://wiki.osdev.org/Entering_Long_Mode_Directly
      http://f.osdev.org/viewtopic.php?f=1&t=16275

  2.   杰羅尼莫 他說:

    首先,您的貢獻非常好,但我認為標題應該是
    “模仿理查德·斯托曼”,或者至少我是這樣認為的,
    問候

    1.    Abimaelmartell 他說:

      Linus創建了Linux內核,Stallman創建了GNU,這是Unix的工具和命令。

      標題是適當的,因為您正在創建一個核。

      您好!

  3.   紅寶石 他說:

    非常感謝您回答我的所有問題並耐心等待,作為一個彙編程序,我只了解基礎知識,而作為C幾乎不了解,但是我非常喜歡它,現在我對GDT有點困惑,讓我們看看是否理解。

    GDT將具有可始終由任何程序訪問的全局“描述符”,並且這些描述符指向將要執行(程序)的部分? 否則就是這樣。