Linus Torvaldsi jäljendamine: looge oma operatsioonisüsteem väärtusest 0 (V)

Selles viiendas osas näeme GDT-ga üsna sarnast tabelit nii teoreetiliselt kui ka kasutuses, viidame IDT-le. IDT tähistab Katkestab kirjeldustabeli y on tabel, mida kasutatakse toimuvate katkestuste käsitlemiseks. Näiteks jagab keegi 0-ga, nimetatakse töötlemise eest vastutavat funktsiooni. Need funktsioonid on ISR (Katkestage teeninduskord). Nii et loome IDT ja lisame ISR-i.

Kõigepealt kuulutame välja IDT-le vastavad struktuurid:

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

Nagu näha, kui võrrelda seda GDT-ga, on Ptr struktuur identne ja kirje üsna sarnane. Seetõttu on kirje (SetGate) ja installi (Install) funktsioonid väga sarnased.

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

Installige:

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

Kui vaatame, näeme, et installifunktsioon kasutab funktsiooni ND :: Memory :: Set, mille olime teises postituses deklareerinud. Samuti võime hinnata, kuidas me veel ei helista SetGate'ile ja kutsume ND :: IDT :: Flush, selle funktsiooni jaoks kasutame uuesti asm volatile lauset:

asm volatile("lidtl (idtptr)");

Kui kõik läheb hästi ja me teeme esteetilise paigutuse, peaks see välja nägema järgmine:

JärgmineDivel-IDT

Okei, nüüd hakkame IDT-d katkestustega täitma. Siin kavatsen luua ainult ühe, kuid ülejäänud osas oleks see sama. Ma hakkan jagama nullmurdega. Nagu matemaatikas hästi teate, ei saa arvu jagada nulliga. Kui see juhtub protsessoris, luuakse erand, kuna see ei saa jätkuda. IDT-s vastab loendi (0) esimene katkestus sellele sündmusele.

Lisame selle mälusätte ja IDT-i installifunktsiooni vahele:

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

Tagasihelistamisfunktsioon saab olema ND :: ISR :: ISR1, mis on üsna lihtne, kuigi peame kasutama ASM-i:

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

ND_ISR_Common määratleme selle funktsioonina C-keeles. Failide salvestamiseks ja loetavuse parandamiseks võime kasutada välist «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"
);
}

See kood ASM-is võib olla natuke raskesti mõistetav, kuid selle põhjuseks on see, et me kuulutame välja struktuuri C-s, et pääseda juurde katkestuse loodud andmetele. Muidugi, kui te seda ei tahtnud, võite lihtsalt helistada tuumapaanikale ND :: ISR :: ISR1 või midagi sellist. Struktuur on sellise kujuga, et:

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

Ja lõpuks teeme funktsiooni ND_ISR_Handler (ka C-lingiga), milles näitame tuuma paanikat ja väikest vea kirjeldust vastavalt sellele, mis meil on vigade loendis.

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

Hea ja sellega oleme selle katkestusega juba hakkama saanud. Ülejäänud katkestuste korral juhtuks see sarnaselt, välja arvatud need, mis tagastavad parameetrid ja selle saamiseks kasutaksime reg-struktuuri. Võite siiski imestada, kuidas me teame, kas see tõesti töötab. Kas see töötab, tutvustame lihtsat rida pärast ND :: IDT :: Install ():

int sum=10/0;

Kui selle koostame, annab see meile hoiatuse ja kui proovime seda täita, saame kena ekraani:

JärgmineDivel-ISR


Ja sellega see postitus lõpeb, arvan, et see on üks kõige ulatuslikum, kuid üsna funktsionaalne.


Jäta oma kommentaar

Sinu e-postiaadressi ei avaldata. Kohustuslikud väljad on tähistatud *

*

*

  1. Andmete eest vastutab: Miguel Ángel Gatón
  2. Andmete eesmärk: Rämpsposti kontrollimine, kommentaaride haldamine.
  3. Seadustamine: teie nõusolek
  4. Andmete edastamine: andmeid ei edastata kolmandatele isikutele, välja arvatud juriidilise kohustuse alusel.
  5. Andmete salvestamine: andmebaas, mida haldab Occentus Networks (EL)
  6. Õigused: igal ajal saate oma teavet piirata, taastada ja kustutada.

  1.   mesodabler DIJO

    Ma läksin üle LFS-ile, see on pidevam.

  2.   eliotime3000 DIJO

    Püha ... Igatahes on õpetused head.

  3.   sc DIJO

    Väga hea, olen seda algusest peale jälginud. Kas saaksite koodid igale treilerile lisada?

    1.    AdrianArroyo tänav DIJO

      Teil on GitHubis saadaval kõik lähtekood: http://github.com/AdrianArroyoCalle/next-divel Sealt saate alla laadida ZIP-i, TAR.GZ-i või lihtsalt kasutada git-i.

  4.   nüansirikas DIJO

    Hahaha väga hea! Kinnita! 🙂