Linus Torvaldsin jäljitteleminen: Luo oma käyttöjärjestelmäsi tyhjästä (IV)

Tervetuloa takaisin tähän vierasarjaan nimeltä "Emuloimalla Linus Torvaldsia". Tänään näemme GDT: n. Ensin täytyy nähdä, mikä GDT on. Wikipedian mukaan:

- Globaali kuvaajataulukko or GDT on tietorakenne, jota käyttää Intel x86-perheen prosessorit, jotka alkavat 80286 määritettäessä ohjelman suorituksen aikana käytettyjen eri muistialueiden ominaisuudet, mukaan lukien perusosoite, koko ja käyttöoikeudet, kuten suoritettavuus ja kirjoitettavuus

Käännettynä olisi Global Descriptor Table, tietorakenne, jota Intel x86 -prosessoreissa on käytetty vuodesta 80286 lähtien määrittelemään ohjelman suorituksen aikana käytettyjen eri muistialueiden ominaisuudet.

Lyhyesti sanottuna, jos käytämme Intel x86 -prosessoria, meidän on määritettävä GDT muistin oikeaan käyttöön. Emme aio tehdä paljon komplikaatioita ja aiomme määrittää 3 merkintää taulukkoon:

  • NULL-merkintä vaaditaan kaikille taulukoille.
  • Lippu osastolle tiedot, käytämme enimmäismäärää, joka on 32 bittiä 4 Gt.
  • Lippu osastolle koodi, käytämme enimmäismäärää, joka on 32 bittiä 4 Gt.

Kuten näette, data ja koodi käyttävät samaa tilaa. Ok, nyt aiomme toteuttaa sen. Tätä varten käytämme kahta rakennetta, joista ensimmäinen on vastuussa osoittimen sisällyttämisestä GDT: n todellisiin tietoihin. Ja toinen on taulukko GDT-merkinnöillä. Määritellään ne ensin

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

Olet ehkä huomannut utelias __attribute __ ((pakattu)) rakenteiden päässä. Tämä käskee GCC: tä olemaan optimoimatta rakenteita, koska haluamme siirtää tiedot sellaisenaan prosessorille. Nyt aiomme tehdä toiminnon GDT: n asentamiseksi. Ennen kuin meidän olisi pitänyt ilmoittaa rakenteet, nyt alustat ne.

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

Joten meidän on rakennettava osoitin, joka menee 3-syötteiseen taulukkoon.

Jos käännät 64 bittiä, se todennäköisesti epäonnistuu täällä. Tämä johtuu siitä, että 64-bittisten järjestelmien osoittimet ovat ilmeisesti 64-bittisiä, ja käytämme täällä 32-bittisiä tyyppejä. -M32-vaihtoehdon käyttäminen voi auttaa toistaiseksi
Nyt määritellään yhteinen toiminto tietojen sijoittamiseksi tuloihin

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

Ja kutsumme sitä 3 kertaa asennustoiminnosta

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

Lopuksi meidän on kerrottava prosessorille, että meillä on GDT, jotta se voi ladata sen, ja tapauksessamme, kun ydintä ladataan GRUB: lla, korvaa GRUB GDT. GDT: n lataamiseen on asm: ssa käsky nimeltä lgdt (tai lgdtl syntaksista riippuen), aiomme käyttää sitä.

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

No, kun tämä on valmis, järjestelmällämme on jo GDT. Seuraavassa luvussa näemme IDT: n, joka on hyvin samanlainen kuin GDT, mutta keskeytyksillä. Olen lisännyt joitain tila- ja vahvistusviestejä GDT: hen, joten NextDivel näyttää nyt tältä:

SeuraavaDivel-GDT


Jätä kommentti

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *

*

*

  1. Vastuussa tiedoista: Miguel Ángel Gatón
  2. Tietojen tarkoitus: Roskapostin hallinta, kommenttien hallinta.
  3. Laillistaminen: Suostumuksesi
  4. Tietojen välittäminen: Tietoja ei luovuteta kolmansille osapuolille muutoin kuin lain nojalla.
  5. Tietojen varastointi: Occentus Networks (EU) isännöi tietokantaa
  6. Oikeudet: Voit milloin tahansa rajoittaa, palauttaa ja poistaa tietojasi.

  1.   saeron dijo

    Ehkä 64-bittinen rakenne sopii paremmin näihin aikoihin, on viive jatkaa 8086: n käyttöä.

    1.    AdrianArroyoKatu dijo

      Olen etsinyt tietoa GDT: stä x86_64: ssä ja mielestäni se seuraa vanhaa mallia erityisellä lipulla. 32-bittistä osoitetta käytetään edelleen. Nyt en tiedä tarkalleen, miten se tehdään oikein. Joitakin linkkejä:
      http://wiki.osdev.org/Entering_Long_Mode_Directly
      http://f.osdev.org/viewtopic.php?f=1&t=16275

  2.   geronimo dijo

    Ensimmäinen erittäin hyvä panoksesi, mutta mielestäni otsikon pitäisi olla
    "Emuloimalla Richard Stallmania" tai ainakin luulen niin ,,,
    terveiset

    1.    abimaelmartell dijo

      Linus loi Linux-ytimen, Stallman loi GNU: n, jotka ovat Unixin työkaluja ja komentoja.

      Otsikko on sopiva, koska olet luomassa ydintä.

      Tervehdys!

  3.   Rubiini dijo

    Paljon kiitoksia vastauksistani kaikkiin kysymyksiini ja kärsivällisyydestä, kokoonpanijana tiedän vain perusasiat ja C: nä melkein mitään, mutta pidän siitä todella, nyt olen hieman hämmentynyt GDT: n kanssa, katsotaanpa ymmärränkö.

    GDT: llä on maailmanlaajuiset 'kuvaimet', joihin pääsee aina millä tahansa ohjelmalla, ja nämä kuvaimet osoittavat osiot, joissa (ohjelma) aiotaan suorittaa? tai se on toisin.