Efterligne Linus Torvalds: Opret dit eget operativsystem fra bunden (IV)

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.

Hvis du kompilerer ved hjælp af 64 bits, vil det sandsynligvis mislykkes her. Dette skyldes, at henvisninger på 64-bit-systemer naturligvis er 64-bit, og vi bruger 32-bit-typer her. Brug af -m32-indstillingen kan hjælpe til nu
Nu definerer vi en fælles funktion til at placere dataene i input

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:

NæsteDivel-GDT


Efterlad din kommentar

Din e-mailadresse vil ikke blive offentliggjort. Obligatoriske felter er markeret med *

*

*

  1. Ansvarlig for dataene: Miguel Ángel Gatón
  2. Formålet med dataene: Control SPAM, management af kommentarer.
  3. Legitimering: Dit samtykke
  4. Kommunikation af dataene: Dataene vil ikke blive kommunikeret til tredjemand, undtagen ved juridisk forpligtelse.
  5. Datalagring: Database hostet af Occentus Networks (EU)
  6. Rettigheder: Du kan til enhver tid begrænse, gendanne og slette dine oplysninger.

  1.   saeron sagde han

    Måske er en 64-bit struktur mere egnet til disse tider, det er et efterslæb at fortsætte med at bruge 8086.

    1.    AdrianArroyoStreet sagde han

      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

  2.   Geronimo sagde han

    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

    1.    abimaelmartell sagde han

      Linus oprettede Linux-kernen, Stallman oprettede GNU, som er Unix-værktøjer og kommandoer.

      Titlen er passende, fordi du opretter en kerne.

      Greetings!

  3.   Rubin sagde han

    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.