Kopiante Linus Torvalds: Kreu vian propran operaciumon de nulo (IV)

Bonvenon reen al ĉi tiu serio de afiŝoj titolita "Emulante Linus Torvalds". Hodiaŭ ni vidos la GDT. Unue ni devas vidi, kio estas la GDT. Laŭ Vikipedio:

la Tutmonda Priskriba Tabelo or GDT estas datuma strukturo uzata de intel x86-familiaj procesoroj komencante per la 80286 por difini la karakterizaĵojn de la diversaj memorareoj uzataj dum programo-ekzekuto, inkluzive de la baza adreso, la grandeco kaj aliraj privilegioj kiel plenumeblo kaj skribeblo

Kio tradukita estus Tutmonda Descripta Tablo, datuma strukturo uzata en procesoroj Intel x86 ekde 80286 por difini la karakterizaĵojn de diversaj memorareoj uzataj dum programo-ekzekuto.

Resume, se ni uzas procesoron Intel x86, ni devas difini GDT por ĝusta uzo de memoro. Ni ne faros multan komplikaĵon kaj ni difinos 3 enirojn en la tabelo:

  • NULA eniro, necesa por ĉiuj tabeloj.
  • Bileto por la sekcio datumoj, ni uzos la maksimumon, kiu en 32 bitoj estas 4 GB.
  • Bileto por la sekcio kodo, ni uzos la maksimumon, kiu en 32 bitoj estas 4 GB.

Kiel vi povas vidi, datumoj kaj kodo uzos la saman spacon. Bone, nun ni efektivigos ĝin. Por ĉi tio ni uzos du strukturojn, la unua estos zorge enhavi montrilon al la realaj datumoj de nia GDT. Kaj la dua estos tabelo kun la GDT-eniroj. Ni unue difinu ilin

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

Vi eble rimarkis scivoleman __atributon__ ((pakita)) ĉe la fino de la strukturoj. Ĉi tio diras al GCC ne optimumigi la strukturojn, ĉar ni volas transdoni la datumojn tiel, kiel estas al la procesoro. Nun ni plenumos funkcion por instali la GDT. Antaŭ ol ni devintus deklari la strukturojn, nun ni pravalorizos ilin.

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

Do ni ekkonstruas la montrilon, kiu iras al nia 3-eniga tabelo.

Se vi kompilas uzante 64 bitojn, ĝi verŝajne malsukcesos ĉi tie. Ĉi tio estas ĉar montriloj sur 64-bitaj sistemoj evidente estas 64-bitaj kaj ni uzas 32-bitajn specojn ĉi tie. Uzi la opcion -m32 eble helpos nuntempe
Nun ni difinas komunan funkcion por meti la datumojn en la enigaĵojn

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

Kaj ni nomas ĝin 3 fojojn de la instalfunkcio

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

Fine ni devas diri al la procesoro, ke ni havas GDT, por ke ĝi povu ŝarĝi ĝin, kaj en nia kazo, kiam ni ŝarĝas la kernon per GRUB, anstataŭigu la GRUB GDT. Por ŝarĝi la GDT estas instrukcio en asm nomata lgdt (aŭ lgdtl depende de la sintakso), ni uzos ĝin.

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

Nu, post kiam ni finos ĉi tion, nia sistemo jam havos GDT. En la sekva ĉapitro ni vidos la IDT, tabelon tre similan al la GDT sed kun interrompoj. Mi metis iujn statusajn kaj konfirmajn mesaĝojn kun la GDT do NextDivel nun aspektas tiel:

NextDivel-GDT


La enhavo de la artikolo aliĝas al niaj principoj de redakcia etiko. Por raporti eraron alklaku Ĉi tie.

5 komentoj, lasu la viajn

Lasu vian komenton

Via retpoŝta adreso ne estos eldonita. Postulita kampojn estas markita per *

*

*

  1. Respondeculo pri la datumoj: Miguel Ángel Gatón
  2. Celo de la datumoj: Kontrola SPAM, administrado de komentoj.
  3. Legitimado: Via konsento
  4. Komunikado de la datumoj: La datumoj ne estos komunikitaj al triaj krom per laŭleĝa devo.
  5. Stokado de datumoj: Datumbazo gastigita de Occentus Networks (EU)
  6. Rajtoj: Iam ajn vi povas limigi, retrovi kaj forigi viajn informojn.

  1.   saeron diris

    Eble 64-bita strukturo pli taŭgas por ĉi tiuj tempoj, ĝi estas postrestanta por daŭre uzi la 8086.

    1.    AdrianArroyoStreet diris

      Mi serĉis informojn pri GDT en x86_64 kaj mi pensas, ke ĝi sekvas la malnovan modelon kun speciala flago. 32-bita adreso estas ankoraŭ uzata. Nun mi ne scias precize kiel fari ĝin ĝuste. Iuj ligoj:
      http://wiki.osdev.org/Entering_Long_Mode_Directly
      http://f.osdev.org/viewtopic.php?f=1&t=16275

  2.   geronimo diris

    La unua tre bona viaj kontribuoj, sed mi pensas, ke la titolo devas esti
    "Emulante Richard Stallman" aŭ almenaŭ mi pensas ke jes,
    salutoj

    1.    abimaelmartell diris

      Linus kreis la Linuksan kernon, Stallman kreis GNU, kiuj estas la Uniksaj iloj kaj komandoj.

      La titolo taŭgas ĉar vi kreas kernon.

      Un saluto!

  3.   Rubeno diris

    Koran dankon pro via respondo al ĉiuj miaj demandoj kaj pacienco, mi nur konas la bazojn kiel asembleo kaj mi scias preskaŭ nenion pri C, sed mi tre ŝatas ĝin, nun mi iom konfuziĝas kun la GDT, ni vidu ĉu mi komprenas.

    GDT havos la tutmondajn 'priskribilojn' al kiuj ĉiam alireblas iu ajn programo, kaj ĉi tiuj priskribiloj montras la sekciojn, kie (la programo) estos plenumata? aŭ ĝi estas alimaniere.