Velkommen tilbage til denne serie indlæg med titlen "Emulating Linus Torvalds". I dag vil vi se GDT. Først skal vi se, hvad GDT er. Ifølge Wikipedia:
Global deskriptor-tabel or GDT er en datastruktur, der bruges af Intel x86-familieprocessorer, der starter med 80286 for at definere karakteristika for de forskellige hukommelsesområder, der bruges under programudførelse, inklusive baseadresse, størrelse og adgangsrettigheder som eksekverbarhed og skrivbarhed
Hvad der oversættes ville være en Global Descriptor Table, en datastruktur, der er brugt i Intel x86-processorer siden 80286 til at definere karakteristika for forskellige hukommelsesområder, der bruges under programudførelse.
Kort sagt, hvis vi bruger en Intel x86-processor, skal vi definere en GDT til korrekt brug af hukommelse. Vi kommer ikke til at gøre meget komplikationer, og vi definerer 3 poster i tabellen:
- En NULL-post, krævet til alle tabeller.
- En billet til sektionen data, vi bruger det maksimale, som i 32 bit er 4 GB.
- En billet til sektionen kode, vi bruger det maksimale, som i 32 bit er 4 GB.
Som du kan se, bruger data og kode det samme rum. Ok, nu skal vi implementere det. Til dette vil vi bruge to strukturer, den første har ansvaret for at indeholde en markør til de reelle data i vores GDT. Og den anden vil være en matrix med GDT-poster. Lad os definere dem først
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));
Du har måske bemærket en nysgerrig __attribut __ ((pakket)) i slutningen af strukturer. Dette fortæller GCC, at de ikke skal optimere strukturerne, fordi det, vi ønsker, er at videregive dataene som til processoren. Nu skal vi lave en funktion til at installere GDT. Før vi skulle have erklæret strukturerne, skal vi nu initialisere dem.
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;
}
Således får vi opbygget markøren, der går til vores 3-input tabel.
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;
}
Og vi kalder det 3 gange fra installationsfunktionen
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 */
Endelig skal vi fortælle processoren, at vi har en GDT, så den kan indlæse den, og i vores tilfælde når du indlæser kernen med GRUB, overskriver du GRUB GDT. For at indlæse GDT er der en instruktion i asm kaldet lgdt (eller lgdtl afhængigt af syntaksen), vi skal bruge den.
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"
);
Når vi er færdige med dette, har vores system allerede GDT. I det næste kapitel ser vi IDT, en tabel, der ligner GDT, men med afbrydelser. Jeg har lagt nogle status- og bekræftelsesmeddelelser med GDT, så NextDivel ser nu sådan ud:
5 kommentarer, lad dine
Måske er en 64-bit struktur mere egnet til disse tider, det er et efterslæb at fortsætte med at bruge 8086.
Jeg har ledt efter oplysninger om GDT i x86_64, og jeg tror, at den følger den gamle model med et specielt flag. En 32-bit adresse bruges stadig. Nu ved jeg ikke nøjagtigt, hvordan man gør det korrekt. Nogle links:
http://wiki.osdev.org/Entering_Long_Mode_Directly
http://f.osdev.org/viewtopic.php?f=1&t=16275
Den første meget gode dine bidrag, men jeg synes titlen skulle være
"Efterligning af Richard Stallman" eller i det mindste tror jeg det ,,,
hilsen
Linus oprettede Linux-kernen, Stallman oprettede GNU, som er Unix-værktøjer og kommandoer.
Titlen er passende, fordi du opretter en kerne.
Greetings!
Mange tak for at have besvaret alle mine spørgsmål og være tålmodig, jeg kender kun det grundlæggende som en assembler og næsten intet om C, men jeg kan godt lide det meget, nu er jeg lidt forvirret med GDT, lad os se om jeg forstår .
GDT vil have de globale 'deskriptorer', der altid kan tilgås af ethvert program, og disse deskriptorer peger på det afsnit, hvor (programmet) skal udføres? eller det er ellers.