Linus Torvalds utánzása: Hozzon létre saját operációs rendszert 0 (V) értékből

Ebben az ötödik részletben a GDT-hez elméletben és használatban is teljesen hasonló táblázatot fogunk látni, utalunk az IDT-re. Az IDT jelentése Megszakítja a leírástáblát y egy tábla, amely a bekövetkező megszakítások kezelésére szolgál. Például valaki 0-val oszt fel, meghívja a feldolgozásért felelős függvényt. Ezek a funkciók az ISR (Szolgáltatás megszakítása). Tehát hozzuk létre az IDT-t és adjunk hozzá néhány ISR-t.

Először deklaráljuk az IDT-nek megfelelő struktúrákat:

struct Entry{
uint16_t base_low;
uint16_t sel;
uint8_t always0;
uint8_t flags;
uint16_t base_high;
} __attribute__((packed));
struct Ptr{
uint16_t limit;
uint32_t base;
} __attribute__((packed));

Amint az látható, ha összehasonlítja a GDT-vel, a Ptr felépítése megegyezik, az Entry pedig nagyon hasonló. Ezért a bejegyzés (SetGate) és a (Install) telepítésének funkciói nagyon hasonlóak.

void ND::IDT::SetGate(uint8_t num,uint32_t base,uint16_t sel, uint8_t flags)
{
idt[num].base_low=(base & 0xFFFF);
idt[num].base_high=(base >> 16) & 0xFFFF;
idt[num].sel=sel;
idt[num].always0=0;
idt[num].flags=flags;
}

Telepítés:

idtptr.limit=(sizeof(struct ND::IDT::Entry)*256)-1;
idtptr.base=(uint32_t)&idt;
ND::Memory::Set(&idt,0,sizeof(struct ND::IDT::Entry)*256);
ND::IDT::Flush();

Ha megnézzük, látni fogjuk, hogy a telepítési függvény az ND :: Memory :: Set függvényt használja, amelyet a másik bejegyzésben deklaráltunk. Nagyra értékelhetjük azt is, hogy még nem hívunk a SetGate-re, és hívjuk az ND :: IDT :: Flush-t, ehhez a funkcióhoz ismét használjuk az asm volatile utasítást:

asm volatile("lidtl (idtptr)");

Ha minden jól megy, és esztétikus elrendezést készítünk, annak így kell kinéznie:

KövetkezőDivel-RTD

Oké, most megkezdjük az IDT megszakításokkal történő feltöltését. Itt csak egyet fogok létrehozni, de a többinek ugyanaz lenne. Meg fogom csinálni az osztást nulla töréssel. Mint jól ismeri a matematikában, egy szám nem osztható 0-val. Ha ez a processzorban történik, akkor egy kivétel jön létre, mivel az nem folytatódhat. Az IDT-ben a (0) lista első megszakítása ennek az eseménynek felel meg.

Ezt hozzáadjuk a memóriabeállítás és az IDT Telepítés funkciójának öblítése közé:

ND::IDT::SetGate(0,(unsigned)ND::ISR::ISR1,0x08,0x8E);

A visszahívási funkció ND :: ISR :: ISR1 lesz, ami meglehetősen egyszerű, bár az ASM-et kell használnunk:

void ND::ISR::ISR1()
{
asm volatile(
"cli \n"
"pushl 0 \n"
"pushl 0 \n"
"jmp ND_ISR_Common \n"
);
}

Meghatározzuk az ND_ISR_Common függvényt C nyelven. A fájlok mentéséhez és az olvashatóság javításához használhatjuk a "C" külsõt {}:

extern "C"
void ND_ISR_Common()
{
asm volatile(
"pusha \n"
"push %ds \n"
"push %es \n"
"push %fs \n"
"push %gs \n"
"movw $0x10, %ax \n"
"movw %ax, %ds \n"
"movw %ax, %es \n"
"movw %ax, %fs \n"
"movw %ax, %gs \n"
"movl %esp, %eax \n"
"push %eax \n"
"movl $ND_ISR_Handler, %eax \n"
"call *%eax \n"
"popl %eax \n"
"popl %ds \n"
"popl %es \n"
"popl %fs \n"
"popl %gs \n"
"popa \n"
"addl 8, %esp \n"
"iret \n"
);
}

Ez a kód az ASM-ben kissé nehezen érthető, de ez azért van, mert deklarálni fogunk egy struktúrát C-ben, hogy hozzáférjünk a megszakítás által generált adatokhoz. Nyilvánvaló, hogy ha nem ezt akarja, akkor egyszerűen felhívhatja a kernelpánikot az ND :: ISR :: ISR1 vagy valami hasonló módon. A szerkezet olyan alakú, hogy:

struct regs{
uint32_t ds;
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
uint32_t int_no, err_code;
uint32_t eip, cs, eflags, useresp, ss;
};

Végül elvégezzük az ND_ISR_Handler függvényt (szintén C linkkel), amelyben egy kernelpánikot és egy apró leírást mutatunk be a hibáról, a hibalista szerint.

extern "C"
void ND_ISR_Handler(struct regs *r)
{
if(r->int_no < 32) { ND::Panic::Show(exception_messages[r->int_no]);
for(;;);
}
}

Jó, és ezzel már képesek vagyunk kezelni ezt a megszakítást. A többi megszakítással hasonlóan történne, kivéve, hogy vannak olyanok, amelyek paramétereket adnak vissza, és a reg struktúrát használnánk annak megszerzésére. Azonban elgondolkodhat azon, hogy honnan tudjuk, hogy valóban működik-e. Hogy teszteljük-e, működik-e egy egyszerű sor az ND :: IDT :: Install () után:

int sum=10/0;

Ha összeállítjuk, figyelmeztetést kapunk, és ha megpróbáljuk végrehajtani, akkor szép képernyőt kapunk:

KövetkezőDivel-ISR


És ezzel véget ér ez a bejegyzés, azt hiszem, ez az egyik legszélesebb körű, de meglehetősen funkcionális.


Hagyja megjegyzését

E-mail címed nem kerül nyilvánosságra. Kötelező mezők vannak jelölve *

*

*

  1. Az adatokért felelős: Miguel Ángel Gatón
  2. Az adatok célja: A SPAM ellenőrzése, a megjegyzések kezelése.
  3. Legitimáció: Az Ön beleegyezése
  4. Az adatok közlése: Az adatokat csak jogi kötelezettség alapján továbbítjuk harmadik felekkel.
  5. Adattárolás: Az Occentus Networks (EU) által üzemeltetett adatbázis
  6. Jogok: Bármikor korlátozhatja, helyreállíthatja és törölheti adatait.

  1.   mesodabler dijo

    LFS-re váltottam, ez folytonosabb.

  2.   eliotime3000 dijo

    Szent ... Egyébként az oktatóanyagok jók.

  3.   sc dijo

    Nagyon jó, kezdettől fogva követtem. Csatolhatná a kódokat az egyes pótkocsikhoz?

    1.    AdrianArroyoStreet dijo

      Az összes forráskód rendelkezésre áll a GitHubon: http://github.com/AdrianArroyoCalle/next-divel Innen letölthet egy ZIP-t, egy TAR.GZ-t, vagy csak használhatja a git-et.

  4.   árnyalt dijo

    Hahaha nagyon jó! Jóváhagy! 🙂