Oponašanje Linusa Torvaldsa: Stvorite vlastiti operativni sustav od 0 (V)

U ovom petom dijelu vidjet ćemo tablicu koja je prilično slična GDT-u i u teoriji i u uporabi, pozivamo se na IDT. IDT je ​​kratica Tabela opisa prekida y je tablica koja se koristi za obradu nastalih prekida. Na primjer, netko napravi podjelu s 0, poziva se funkcija zadužena za obradu. Te su funkcije ISR (Rutine usluga prekida). Pa kreirajmo IDT i dodajte malo ISR-a.

Prvo ćemo proglasiti strukture koje odgovaraju IDT-u:

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

Kao što se može vidjeti ako ga usporedite s GDT-om, Ptr struktura je identična, a Entry je prilično slična. Stoga su funkcije stavljanja unosa (SetGate) i instalacije (Install) vrlo slične.

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

Instalirati:

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

Ako pogledamo, vidjet ćemo da funkcija instalacije koristi funkciju ND :: Memory :: Set koju smo deklarirali u drugom postu. Također možemo vidjeti kako još ne upućujemo pozive SetGateu i pozivamo ND :: IDT :: Flush, za ovu funkciju ponovno koristimo asm volatile izraz:

asm volatile("lidtl (idtptr)");

Ako sve bude u redu i napravimo estetski aranžman, to bi trebalo izgledati ovako:

NextDivel-RTD

U redu, sada ćemo početi puniti IDT prekidima. Ovdje ću stvoriti samo jedan, ali za ostalo bi bilo isto. Idem napraviti podjelu s nulom. Kao što dobro znate u matematici, broj se ne može podijeliti s 0. Ako se to dogodi u procesoru, generira se iznimka jer se ne može nastaviti. U IDT-u prvi prekid na popisu (0) odgovara ovom događaju.

Ovo dodajemo između postavke memorije i ispiranja unutar funkcije Instaliranje IDT-a:

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

Funkcija povratnog poziva bit će ND :: ISR :: ISR1 što je vrlo jednostavno, iako moramo koristiti ASM:

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

ND_ISR_Common definirat ćemo je kao funkciju na jeziku C. Za spremanje datoteka i poboljšanje čitljivosti možemo koristiti eksterni «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"
);
}

Ovaj kôd u ASM-u može biti pomalo teško razumjeti, ali to je zato što ćemo proglasiti strukturu u C-u za pristup podacima generiranim prekidom. Očito, ako to niste željeli, možete jednostavno nazvati Kernel Panic u ND :: ISR :: ISR1 ili nešto slično. Struktura ima takav oblik da:

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

I na kraju napravimo funkciju ND_ISR_Handler (također s C vezom) u kojoj pokazujemo paniku kernela i mali opis pogreške prema onoj koju imamo na popisu pogrešaka.

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

Dobro, a time se već možemo nositi s tim prekidom. S ostalim prekidima dogodilo bi se slično, osim što postoje neki koji vraćaju parametre, a mi bismo za dobivanje koristili reg strukturu. Međutim, možda se pitate kako znamo znamo li to doista. Da bismo testirali radi li, uvest ćemo jednostavni redak nakon ND :: IDT :: Install ():

int sum=10/0;

Ako kompajliramo, dat će nam upozorenje i ako ga pokušamo izvršiti, dobit ćemo lijep zaslon:

NextDivel-ISR


I ovim završava ovaj post, mislim da je jedan od najopsežnijih, ali prilično funkcionalan.


Ostavite svoj komentar

Vaša email adresa neće biti objavljen. Obavezna polja su označena s *

*

*

  1. Za podatke odgovoran: Miguel Ángel Gatón
  2. Svrha podataka: Kontrola neželjene pošte, upravljanje komentarima.
  3. Legitimacija: Vaš pristanak
  4. Komunikacija podataka: Podaci se neće dostavljati trećim stranama, osim po zakonskoj obvezi.
  5. Pohrana podataka: Baza podataka koju hostira Occentus Networks (EU)
  6. Prava: U bilo kojem trenutku možete ograničiti, oporaviti i izbrisati svoje podatke.

  1.   mesodabler dijo

    Prebacio sam se na LFS, on je kontinuiraniji.

  2.   eliotime3000 dijo

    Sveto ... Svejedno, tutorijali su dobri.

  3.   sc dijo

    Vrlo dobro, pratim ga od početka. Možete li priložiti kodove svakoj prikolici?

    1.    AdrianArroyoStreet dijo

      Na GitHubu imate dostupan sav izvorni kod: http://github.com/AdrianArroyoCalle/next-divel Odatle možete preuzeti ZIP, TAR.GZ ili jednostavno koristiti git.

  4.   nijansiran dijo

    Hahaha jako dobro! Odobriti! 🙂