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.
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ä:
Ehkä 64-bittinen rakenne sopii paremmin näihin aikoihin, on viive jatkaa 8086: n käyttöä.
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
Ensimmäinen erittäin hyvä panoksesi, mutta mielestäni otsikon pitäisi olla
"Emuloimalla Richard Stallmania" tai ainakin luulen niin ,,,
terveiset
Linus loi Linux-ytimen, Stallman loi GNU: n, jotka ovat Unixin työkaluja ja komentoja.
Otsikko on sopiva, koska olet luomassa ydintä.
Tervehdys!
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.