Emulácia Linusa Torvaldsa: Vytvorte si vlastný operačný systém od 0 (V)

V tomto piatom pokračovaní uvidíme tabuľku, ktorá je teoreticky aj prakticky podobná GDT, označujeme IDT. IDT znamená Tabuľka s popisom prerušení y je tabuľka, ktorá sa používa na spracovanie prerušení, ku ktorým dôjde. Napríklad niekto urobí delenie číslom 0, volá sa funkcia zodpovedná za spracovanie. Tieto funkcie sú ISR (Prerušiť rutinné služby). Poďme teda vytvoriť IDT a pridať nejaké ISR.

Najprv ideme deklarovať štruktúry zodpovedajúce IDT:

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

Ako je vidieť, ak to porovnáte s GDT, štruktúra Ptr je identická a položka je dosť podobná. Preto sú funkcie vloženia záznamu (SetGate) a inštalácie (Install) veľmi podobné.

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

Inštalácia:

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

Ak sa pozrieme, uvidíme, že inštalačná funkcia používa funkciu ND :: Memory :: Set, ktorú sme deklarovali v druhom príspevku. Môžeme tiež vidieť, ako zatiaľ neuskutočňujeme žiadne hovory na SetGate a voláme ND :: IDT :: Flush, pre túto funkciu použijeme opäť asm volatile príkaz:

asm volatile("lidtl (idtptr)");

Ak všetko dobre dopadne a urobíme estetické usporiadanie, malo by to vyzerať takto:

NextDivel-RTD

Dobre, teraz začneme IDT plniť prerušeniami. Tu vytvorím iba jeden, ale pre zvyšok by to bolo rovnaké. Chystám sa urobiť rozdelenie nulovým zlomom. Ako viete v matematike, číslo nemožno vydeliť 0. Ak k tomu dôjde v procesore, vygeneruje sa výnimka, pretože nemôže pokračovať. V IDT zodpovedá prvé prerušenie v zozname (0) tejto udalosti.

Pridávame to medzi nastavenie pamäte a vyprázdnenie v rámci funkcie Inštalácia IDT:

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

Funkcia spätného volania bude ND :: ISR :: ISR1, čo je celkom jednoduché, aj keď musíme použiť ASM:

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

ND_ISR_Common ho definujeme ako funkciu v jazyku C. Na uloženie súborov a zlepšenie čitateľnosti môžeme použiť externý znak «C» {}:

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

Tento kód v ASM môže byť trochu ťažko pochopiteľný, ale je to preto, že v C deklarujeme štruktúru na prístup k údajom generovaným prerušením. Je zrejmé, že ak to nechcete, môžete jednoducho zavolať paniku jadra v ND :: ISR :: ISR1 alebo podobne. Štruktúra má taký tvar, že:

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

A nakoniec urobíme funkciu ND_ISR_Handler (aj s C linkom), v ktorej ukážeme panickú chybu jadra a malý popis chyby podľa tej, ktorú máme v zozname chýb.

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

Dobré a vďaka tomu už toto prerušenie zvládneme. S ostatnými prerušeniami by sa to stalo podobné, až na to, že existujú niektoré, ktoré vracajú parametre, a na ich získanie by sme použili štruktúru reg. Možno by vás však zaujímalo, ako vieme, či to naozaj funguje. Aby sme vyskúšali, či to funguje, po ND :: IDT :: Install () zavedieme jednoduchý riadok:

int sum=10/0;

Ak to skompilujeme, dá nám varovanie a ak sa ho pokúsime vykonať, zobrazí sa nám pekná obrazovka:

NextDivel-ISR


Týmto sa tento príspevok končí, myslím si, že je to jeden z najrozsiahlejších, ale celkom funkčných.


Zanechajte svoj komentár

Vaša e-mailová adresa nebude zverejnená. Povinné položky sú označené *

*

*

  1. Zodpovedný za údaje: Miguel Ángel Gatón
  2. Účel údajov: Kontrolný SPAM, správa komentárov.
  3. Legitimácia: Váš súhlas
  4. Oznamovanie údajov: Údaje nebudú poskytnuté tretím stranám, iba ak to vyplýva zo zákona.
  5. Ukladanie dát: Databáza hostená spoločnosťou Occentus Networks (EU)
  6. Práva: Svoje údaje môžete kedykoľvek obmedziť, obnoviť a vymazať.

  1.   mesodabler dijo

    Išiel som na LFS, je to kontinuálnejšie.

  2.   eliotime3000 dijo

    Svätý ... Každopádne, návody sú dobré.

  3.   sc dijo

    Veľmi dobre, sledujem to od začiatku. Mohli by ste pripojiť kódy ku každému prívesu?

    1.    AdrianArroyoStreet dijo

      Na GitHub máte k dispozícii všetok zdrojový kód: http://github.com/AdrianArroyoCalle/next-divel Odtiaľ si môžete stiahnuť ZIP, TAR.GZ alebo jednoducho použiť git.

  4.   nuansy dijo

    Hahaha veľmi dobre! Schváliť! 🙂