Oponašanje Linusa Torvaldsa: Stvorite vlastiti operativni sustav od nule (IV)

Dobrodošli natrag u ovu seriju postova pod naslovom "Oponašanje Linusa Torvaldsa". Danas ćemo vidjeti GDT. Prvo moramo vidjeti što je GDT. Prema Wikipediji:

Korištenje električnih romobila ističe Globalna tablica deskriptora or GDT je struktura podataka koju koristi Intel x86-obiteljski procesori koji počinju s 80286 kako bi se definirale karakteristike različitih memorijskih područja koja se koriste tijekom izvršavanja programa, uključujući osnovnu adresu, veličinu i privilegije pristupa poput izvršnosti i zapisljivosti

Prevedeno bi bilo Global Descriptor Table, podatkovna struktura koja se koristi u procesorima Intel x86 od 80286 za definiranje karakteristika različitih memorijskih područja koja se koriste tijekom izvršavanja programa.

Ukratko, ako koristimo Intel x86 procesor, moramo definirati GDT za ispravnu upotrebu memorije. Nećemo puno komplicirati i definirat ćemo 3 unosa u tablici:

  • NULL unos, potreban za sve tablice.
  • Ulaznica za dionicu datum, koristit ćemo maksimum, što u 32 bita iznosi 4 GB.
  • Ulaznica za dionicu kod, koristit ćemo maksimum, što u 32 bita iznosi 4 GB.

Kao što vidite, podaci i kod koristit će isti prostor. Ok, sada ćemo to provesti. Za to ćemo upotrijebiti dvije strukture, prva će biti zadužena za sadržavanje pokazivača na stvarne podatke našeg GDT-a. A drugi će biti niz s GDT unosima. Prvo ih definirajmo

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));

Možda ste primijetili znatiželjan __atribut __ ((spakiran)) na kraju struktura. To govori GCC-u da ne optimizira strukture, jer ono što želimo je prosljeđivanje podataka takvima kakvi jesu procesoru. Sada ćemo napraviti funkciju za instaliranje GDT-a. Prije nego što smo trebali proglasiti strukture, sada ćemo ih inicijalizirati.

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;
}

Tako moramo izgraditi pokazivač koji ide do naše tablice s 3 ulaza.

Ako kompajlirate pomoću 64 bita, ovdje najvjerojatnije neće uspjeti. To je zato što su pokazivači na 64-bitnim sustavima očito 64-bitni i mi ovdje koristimo 32-bitne vrste. Korištenje opcije -m32 za sada može pomoći
Sada definiramo zajedničku funkciju za stavljanje podataka u ulaze

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;
}

I pozivamo ga 3 puta iz instalacijske funkcije

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 */

Konačno, moramo reći procesoru da imamo GDT, kako bi ga mogao učitati, au našem slučaju kada učitavamo jezgru GRUB-om, prebrisati GRUB GDT. Za učitavanje GDT-a postoji uputa u asm koja se naziva lgdt (ili lgdtl, ovisno o sintaksi), mi ćemo je koristiti.

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"
);

Pa kad završimo s ovim, naš će sustav već imati GDT. U sljedećem ćemo poglavlju vidjeti IDT, tablicu vrlo sličnu GDT-u, ali s prekidima. Stavio sam neke poruke o statusu i potvrdi s GDT-om, tako da NextDivel sada izgleda ovako:

NextDivel-GDT


Ostavite svoj komentar

Vaša email adresa neće biti objavljen. Obavezna polja su označena s *

*

*

  1. Za podatke odgovoran: Miguel Ángel Gatón
  2. Svrha podataka: Kontrola neželjene pošte, upravljanje komentarima.
  3. Legitimacija: Vaš pristanak
  4. Komunikacija podataka: Podaci se neće dostavljati trećim stranama, osim po zakonskoj obvezi.
  5. Pohrana podataka: Baza podataka koju hostira Occentus Networks (EU)
  6. Prava: U bilo kojem trenutku možete ograničiti, oporaviti i izbrisati svoje podatke.

  1.   saeron dijo

    Možda je 64-bitna struktura prikladnija za ova vremena, zaostatak je za nastavkom korištenja 8086.

    1.    AdrianArroyoStreet dijo

      Tražio sam informacije o GDT-u u x86_64 i mislim da slijedi stari model s posebnom zastavicom. I dalje se koristi 32-bitna adresa. Sad ne znam točno kako to ispravno učiniti. Neke poveznice:
      http://wiki.osdev.org/Entering_Long_Mode_Directly
      http://f.osdev.org/viewtopic.php?f=1&t=16275

  2.   Geronimo dijo

    Prije svega, vaši su doprinosi vrlo dobri, ali mislim da bi naslov trebao biti
    "Oponašanje Richarda Stallmana" ili barem tako mislim ,,,
    pozdravi

    1.    abimaelmartell dijo

      Linus je stvorio Linux kernel, Stallman je stvorio GNU koji su Unixovi alati i naredbe.

      Naslov je prikladan jer stvarate jezgru.

      Pozdrav!

  3.   Rubin dijo

    Puno vam hvala što ste odgovorili na sva moja pitanja i bili strpljivi, osnove znam samo kao asembler i ne znam gotovo ništa o C-u, ali stvarno mi se sviđa, sad sam pomalo zbunjen s GDT-om, da vidimo hoću li razumjeti.

    GDT će imati globalne 'deskriptore' kojima uvijek može pristupiti bilo koji program, a ti deskriptori upućuju na odjeljak u kojem će se (program) izvršiti? ili je inače.