Laipni lūdzam atpakaļ šajā ierakstu sērijā ar nosaukumu "Līnusa Torvalda atdarināšana". Šodien mēs redzēsim GDT. Vispirms mums jāskatās, kas ir GDT. Saskaņā ar Wikipedia:
Jūsu darbs IR Klientu apkalpošana Globālā deskriptoru tabula or GDT ir datu struktūra, kuru izmanto Intel x86- ģimenes procesori, sākot ar 80286 lai noteiktu programmas izpildes laikā izmantoto dažādu atmiņas apgabalu īpašības, tostarp bāzes adresi, lielumu un piekļuves tiesības, piemēram, izpildāmību un rakstāmību
Tulkotā būtu globālā deskriptoru tabula, datu struktūra, ko Intel x86 procesoros izmanto kopš 80286. gada, lai noteiktu dažādu atmiņas apgabalu īpašības, kuras tiek izmantotas programmas izpildes laikā.
Kopumā, ja mēs izmantojam Intel x86 procesoru, mums ir jādefinē GDT pareizai atmiņas lietošanai. Mēs nedarīsim daudz sarežģījumu, un mēs definēsim 3 tabulas ierakstus:
- NULL ieraksts, kas nepieciešams visām tabulām.
- Biļete uz sadaļu dati, mēs izmantosim maksimālo, kas 32 bitos ir 4 GB.
- Biļete uz sadaļu kods, mēs izmantosim maksimālo, kas 32 bitos ir 4 GB.
Kā redzat, dati un kods izmantos vienu un to pašu vietu. Labi, tagad mēs to īstenosim. Šim nolūkam mēs izmantosim divas struktūras, no kurām pirmā būs atbildīga par rādītāja ievietošanu mūsu GDT reālajos datos. Un otrais būs masīvs ar GDT ierakstiem. Vispirms tos definēsim
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));
Iespējams, struktūru beigās esat pamanījis ziņkārīgu __attribute __ ((iepakotu)). Tas liek GCC neoptimizēt struktūras, jo mēs vēlamies nodot datus procesoram. Tagad mēs izveidosim funkciju GDT instalēšanai. Pirms mums vajadzēja deklarēt struktūras, tagad mēs tos inicializēsim.
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;
}
Tādējādi mēs izveidojam rādītāju, kas nonāk mūsu 3 ievades tabulā.
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;
}
Un mēs to saucam 3 reizes no instalēšanas funkcijas
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 */
Visbeidzot, mums procesoram jāpasaka, ka mums ir GDT, lai tas to varētu ielādēt, un mūsu gadījumā, ielādējot kodolu ar GRUB, jāpārraksta GRUB GDT. Lai ielādētu GDT, ASM ir instrukcija, ko sauc par lgdt (vai lgdtl atkarībā no sintakses), mēs to izmantosim.
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"
);
Nu, kad mēs to būsim pabeiguši, mūsu sistēmai jau būs GDT. Nākamajā nodaļā mēs redzēsim IDT - tabulu, kas ir ļoti līdzīga GDT, bet ar pārtraukumiem. Esmu ievietojis dažus statusa un apstiprinājuma ziņojumus GDT, tāpēc NextDivel tagad izskatās šādi:
Varbūt šajos laikos vairāk piemērota ir 64 bitu struktūra, un tas ir neizpildīts, lai turpinātu izmantot 8086.
Esmu meklējis informāciju par GDT failā x86_64, un es domāju, ka tas seko vecajam modelim ar īpašu karodziņu. Joprojām tiek izmantota 32 bitu adrese. Tagad es nezinu, kā to pareizi izdarīt. Dažas saites:
http://wiki.osdev.org/Entering_Long_Mode_Directly
http://f.osdev.org/viewtopic.php?f=1&t=16275
Pirmais ļoti labs jūsu ieguldījums, bet es domāju, ka nosaukumam vajadzētu būt
"Ričarda Stallmana atdarināšana" vai vismaz es tā domāju ,,,
Sveicieni
Linuss izveidoja Linux kodolu, Stalmens - GNU, kas ir Unix rīki un komandas.
Virsraksts ir piemērots, jo jūs veidojat kodolu.
Sveicieni!
Liels paldies, ka atbildējāt uz visiem maniem jautājumiem un esat pacietīgs, es zinu tikai pamatus kā montētājs un gandrīz neko nezinu par C, bet man tas ļoti patīk, tagad esmu mazliet sajaucies ar GDT, paskatīsimies, vai es saprast.
GDT būs globālie “deskriptori”, kuriem vienmēr var piekļūt jebkura programma, un šie deskriptori norāda uz sadaļu, kurā (programma) tiks izpildīta? vai ir citādi.