Lino Torvaldso mėgdžiojimas: sukurkite savo operacinę sistemą iš 0 (V)

Šioje penktoje dalyje pamatysime tiek teoriškai, tiek naudodamiesi gana panašia į GDT lentele, remiamės IDT. IDT reiškia Pertraukia aprašymo lentelę y yra lentelė, kuri naudojama įvykstant pertraukimams. Pavyzdžiui, kažkas padalija iš 0, vadinama funkcija, atsakinga už apdorojimą. Šios funkcijos yra ISR (Nutraukti aptarnavimo tvarką). Taigi sukurkime IDT ir pridėkime šiek tiek ISR.

Pirmiausia deklaruosime IDT atitinkančias struktūras:

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

Kaip matyti iš palyginimo su GDT, Ptr struktūra yra identiška, o įrašas - gana panašus. Todėl įrašo („SetGate“) įdėjimo ir „Įdiegti“ funkcijos yra labai panašios.

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

Diegti:

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

Pažiūrėję pamatysime, kad diegimo funkcija naudoja ND :: Memory :: Set funkciją, kurią buvome deklaravę kitame įraše. Mes taip pat galime įvertinti, kaip dar neskambiname į „SetGate“, ir mes vadiname ND :: IDT :: Flush, šiai funkcijai mes vėl naudojame asm volatile pareiškimą:

asm volatile("lidtl (idtptr)");

Jei viskas gerai ir mes padarome estetinį išdėstymą, tai turėtų atrodyti taip:

„NextDivel-IDT“

Gerai, dabar mes pradėsime pildyti IDT pertraukimais. Čia aš ketinu sukurti tik vieną, bet likusi dalis būtų tokia pati. Aš padarysiu padalijimą iš nulinės pertraukos. Kaip gerai žinote matematikoje, skaičiaus negalima padalyti iš 0. Jei taip nutinka procesoriuje, sukuriama išimtis, nes ji negali tęstis. IDT atveju pirmasis įvykio sąrašo (0) pertraukimas atitinka šį įvykį.

Tai pridedame tarp atminties nustatymo ir „IDT“ įdiegimo funkcijos:

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

Skambinimo funkcija bus ND :: ISR :: ISR1, kuri yra gana paprasta, nors mes turime naudoti ASM:

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

ND_ISR_Common tai apibrėžsime kaip funkciją C kalba. Norėdami išsaugoti failus ir pagerinti skaitomumą, galime naudoti išorinį «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"
);
}

Šį kodą ASM gali būti šiek tiek sunku suprasti, bet taip yra todėl, kad mes paskelbsime C struktūrą, kad galėtume pasiekti pertraukimo generuojamus duomenis. Akivaizdu, kad jei to nenorėjote, galite tiesiog paskambinti į branduolio paniką ND :: ISR :: ISR1 ar panašiai. Struktūra turi tokią formą, kad:

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

Galiausiai sukuriame funkciją ND_ISR_Handler (taip pat su C nuoroda), kurioje parodome branduolio paniką ir nedidelį klaidos aprašymą pagal tą, kurį turime klaidų sąraše.

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

Gerai ir tuo mes jau sugebame sutvarkyti šį pertraukimą. Su likusiais pertraukimais tai nutiktų panašiai, išskyrus tai, kad yra tokių, kurie pateikia parametrus, ir mes norėtume jį naudoti reg struktūrą. Tačiau galite susimąstyti, iš kur mes žinome, ar tai tikrai veikia. Norėdami patikrinti, ar tai veikia, mes pristatysime paprastą eilutę po ND :: IDT :: Install ():

int sum=10/0;

Jei mes jį sudarysime, gausite perspėjimą ir, jei bandysime jį įvykdyti, gausime gražų ekraną:

„NextDivel-ISR“


Tuo pasibaigus, manau, kad jis yra vienas iš plačiausių, tačiau gana funkcionalus.


Palikite komentarą

Jūsų elektroninio pašto adresas nebus skelbiamas. Privalomi laukai yra pažymėti *

*

*

  1. Atsakingas už duomenis: Miguel Ángel Gatón
  2. Duomenų paskirtis: kontroliuoti šlamštą, komentarų valdymą.
  3. Įteisinimas: jūsų sutikimas
  4. Duomenų perdavimas: Duomenys nebus perduoti trečiosioms šalims, išskyrus teisinius įsipareigojimus.
  5. Duomenų saugojimas: „Occentus Networks“ (ES) talpinama duomenų bazė
  6. Teisės: bet kuriuo metu galite apriboti, atkurti ir ištrinti savo informaciją.

  1.   mesodabler sakė

    Aš perėjau į LFS, jis yra tęstinis.

  2.   3000 sakė

    Šventa ... Šiaip ar taip, vadovėliai yra geri.

  3.   sc sakė

    Labai gerai, aš jį stebėjau nuo pat pradžių. Ar galėtumėte pridėti kodus prie kiekvienos priekabos?

    1.    AdrianArroyo gatvė sakė

      Turite visą šaltinio kodą, kurį galite rasti „GitHub“: http://github.com/AdrianArroyoCalle/next-divel Iš ten galite atsisiųsti ZIP, TAR.GZ arba tiesiog naudoti „git“.

  4.   niuansuotas sakė

    Hahaha labai gerai! Patvirtinti! 🙂