Emulace Linuse Torvaldse: Vytvořte si svůj vlastní operační systém od 0 (V)

V této páté splátce uvidíme tabulku docela podobnou GDT, a to jak teoreticky, tak při používání, odkazujeme na IDT. IDT znamená Tabulka přerušení Popis y je tabulka, která se používá ke zpracování přerušení, ke kterým dojde. Například někdo provede dělení 0, volá se funkce zodpovědná za zpracování. Tyto funkce jsou ISR (Přerušit rutiny služeb). Pojďme tedy vytvořit IDT a přidat nějaké ISR.

Nejprve prohlásíme struktury odpovídající 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));

Jak je vidět, pokud jej porovnáte s GDT, struktura Ptr je identická a položka je docela podobná. Funkce vložení položky (SetGate) a instalace (instalace) jsou proto velmi 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;
}

Nainstalujte:

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

Pokud se podíváme, uvidíme, že funkce instalace používá funkci ND :: Memory :: Set, kterou jsme deklarovali v druhém příspěvku. Můžeme také vidět, jak ještě neprovádíme žádná volání SetGate a voláme ND :: IDT :: Flush, pro tuto funkci znovu použijeme volatilní příkaz asm:

asm volatile("lidtl (idtptr)");

Pokud vše půjde dobře a provedeme estetické uspořádání, mělo by to vypadat takto:

DalšíDivel-IDT

Dobře, teď začneme plnit IDT přerušením. Tady vytvořím jen jednu, ale pro zbytek by to bylo stejné. Udělám dělení nulovým zlomem. Jak v matematice dobře víte, číslo nelze vydělit 0. Pokud k tomu dojde v procesoru, vygeneruje se výjimka, protože nemůže pokračovat. V IDT první přerušení v seznamu (0) odpovídá této události.

Přidáme to mezi nastavení paměti a flush v rámci funkce instalace IDT:

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

Funkce zpětného volání bude ND :: ISR :: ISR1, což je docela jednoduché, i když musíme použít ASM:

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

ND_ISR_Common definujeme to jako funkci v jazyce C. Pro uložení souborů a zlepšení čitelnosti můžeme použít externí «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 být trochu obtížné pochopit, ale je to proto, že budeme deklarovat strukturu v C pro přístup k datům generovaným přerušením. Je zřejmé, že pokud jste to nechtěli, stačí zavolat Kernel Panic v ND :: ISR :: ISR1 nebo něco podobného. Struktura má takový 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 nakonec uděláme funkci ND_ISR_Handler (také s odkazem C), ve které ukážeme paniku jádra a malý popis chyby podle té, kterou máme v seznamu chyb.

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

Dobře, a díky tomu už toto přerušení zvládneme. Se zbytkem přerušení by se to stalo podobné, až na to, že existují některé, které vracejí parametry, a k jejich získání bychom použili strukturu reg. Možná se však divíte, jak víme, jestli to opravdu funguje. Abychom vyzkoušeli, zda to funguje, zavedeme po ND :: IDT :: Install () jednoduchý řádek:

int sum=10/0;

Pokud to zkompilujeme, dá nám to varování a pokud se to pokusíme provést, dostaneme pěknou obrazovku:

DalšíDivel-ISR


A tím končí tento příspěvek, myslím, že je to jeden z nejrozsáhlejších, ale docela funkčních.


Zanechte svůj komentář

Vaše e-mailová adresa nebude zveřejněna. Povinné položky jsou označeny *

*

*

  1. Odpovědný za údaje: Miguel Ángel Gatón
  2. Účel údajů: Ovládací SPAM, správa komentářů.
  3. Legitimace: Váš souhlas
  4. Sdělování údajů: Údaje nebudou sděleny třetím osobám, s výjimkou zákonných povinností.
  5. Úložiště dat: Databáze hostovaná společností Occentus Networks (EU)
  6. Práva: Vaše údaje můžete kdykoli omezit, obnovit a odstranit.

  1.   mesodabler řekl

    Přešel jsem na LFS, je to spojitější.

  2.   eliotime3000 řekl

    Svatý ... Výuky jsou každopádně dobré.

  3.   sc řekl

    Velmi dobře, sleduji to od začátku. Můžete připojit kódy ke každému přívěsu?

    1.    AdrianArroyo Street řekl

      Veškerý zdrojový kód máte k dispozici na GitHubu: http://github.com/AdrianArroyoCalle/next-divel Odtud si můžete stáhnout ZIP, TAR.GZ nebo jednoduše použít git.

  4.   odstín řekl

    Hahaha velmi dobře! Schválit! 🙂