Welkom by hierdie reeks plasings getiteld "Emulating Linus Torvalds". Vandag sien ons die GDT. Eerstens moet ons sien wat die GDT is. Volgens Wikipedia:
Die Globale beskrywingstabel or GDT is 'n datastruktuur wat deur Intel x86-familieverwerkers wat begin met die 80286 om die kenmerke van die verskillende geheue-areas wat tydens programuitvoering gebruik word, te definieer, insluitend die basisadres, die grootte en toegangsregte soos uitvoerbaarheid en skryfbaarheid
Wat vertaal word, is 'n Global Descriptor Table, 'n datastruktuur wat sedert 86 in Intel x80286-verwerkers gebruik is om die kenmerke van verskillende geheue-areas wat tydens programuitvoering gebruik word, te definieer.
Kortom, as ons 'n Intel x86-verwerker gebruik, moet ons 'n GDT definieer vir die korrekte gebruik van geheue. Ons gaan nie veel komplikasies doen nie en ons gaan drie inskrywings in die tabel definieer:
- 'N NULL-inskrywing, benodig vir alle tabelle.
- 'N Kaartjie vir die afdeling data, sal ons die maksimum gebruik, wat in 32 bisse 4 GB is.
- 'N Kaartjie vir die afdeling kode, sal ons die maksimum gebruik, wat in 32 bisse 4 GB is.
Soos u kan sien, sal data en kode dieselfde spasie gebruik. Ok, nou gaan ons dit implementeer. Hiervoor gebruik ons twee strukture, waarvan die eerste die wyser bevat van die werklike data van ons GDT. En die tweede sal 'n skikking wees met die GDT-inskrywings. Kom ons definieer dit eers
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));
U het miskien 'n nuuskierige __attribuut __ ((verpak)) opgemerk aan die einde van die strukture. Dit gee aan die GCC om nie die strukture te optimaliseer nie, want wat ons wil hê, is om die data net so aan die verwerker oor te dra. Nou gaan ons 'n funksie maak om die GDT te installeer. Voordat ons die strukture moes verklaar, gaan ons dit nou inisialiseer.
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;
}
Dus kan ons die wyser bou wat na ons 3-invoer-tabel gaan.
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;
}
En ons noem dit 3 keer vanaf die installeringsfunksie
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 */
Ten slotte moet ons aan die verwerker sê dat ons 'n GDT het, sodat dit dit kan laai, en in ons geval wanneer u die kern met GRUB laai, moet u die GRUB GDT oorskryf. Om die GDT te laai, is daar 'n instruksie in asm genaamd lgdt (of lgdtl, afhangende van die sintaksis), ons gaan dit gebruik.
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"
);
As ons dit klaar het, sal ons stelsel reeds GDT hê. In die volgende hoofstuk sal ons die IDT sien, 'n tabel wat baie ooreenstem met die GDT, maar met onderbrekings. Ek het 'n paar status- en bevestigingsboodskappe by die GDT geplaas, so NextDivel lyk nou so:
5 kommentaar, los joune
Miskien is 'n 64-bis-struktuur meer geskik vir hierdie tye, maar dit is 'n agterstand om die 8086 te gebruik.
Ek het op soek na inligting oor GDT in x86_64 en ek dink dit volg die ou model met 'n spesiale vlag. 'N 32-bis adres word steeds gebruik. Nou weet ek nie presies hoe om dit korrek te doen nie. Enkele skakels:
http://wiki.osdev.org/Entering_Long_Mode_Directly
http://f.osdev.org/viewtopic.php?f=1&t=16275
Die eerste baie goeie bydraes, maar ek dink die titel moet wees
"Emulating Richard Stallman" of ten minste dink ek so ,,,
Groete
Linus het die Linux-kern geskep, Stallman het GNU geskep, wat die Unix-gereedskap en -opdragte is.
Die titel is gepas omdat u 'n kern skep.
Groete!
Baie dankie dat u al my vrae beantwoord het en geduldig was, ek ken net die basiese beginsels as 'n samesteller en ek weet amper niks van C nie, maar ek hou daarvan, nou is ek 'n bietjie verward met die GDT, laat ons sien of ek dit verstaan.
Die GDT sal die wêreldwye 'beskrywers' hê wat altyd deur enige program toeganklik is, en hierdie beskrywers wys na die gedeeltes waar (die program) uitgevoer gaan word? of dit is anders.