In hierdie vyfde aflewering sien ons 'n tabel wat soortgelyk is aan die GDT, beide in teorie en in gebruik. Ons verwys na die IDT. IDT staan vir Onderbrekings Beskrywingstabel y is 'n tabel wat gebruik word om onderbrekings wat voorkom, te hanteer. Iemand maak byvoorbeeld 'n deel deur 0, die funksie wat verantwoordelik is vir die verwerking word genoem. Hierdie funksies is die ISR (Onderbreek diensroetines). Laat ons dus die IDT skep en ISR byvoeg.
Eerstens gaan ons die strukture verklaar wat ooreenstem met die 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));
Soos gesien kan word as u dit met die GDT vergelyk, is die Ptr-struktuur identies en die invoer baie gelyk. Daarom is die funksies om 'n inskrywing (SetGate) en installering (Install) te plaas baie dieselfde.
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;
}
Installeer:
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();
As ons kyk, sal ons sien dat die installeringsfunksie die ND :: Memory :: Set-funksie gebruik wat ons in die ander pos verklaar het. Ons kan ook waardeer hoe ons nog geen oproepe na SetGate doen nie en ons noem ND :: IDT :: Flush, vir hierdie funksie gebruik ons die asm-vlugtige stelling weer:
asm volatile("lidtl (idtptr)");
As alles goed gaan en ons 'n estetiese reëling tref, moet dit so lyk:
Goed, nou gaan ons die IDT vul met onderbrekings. Hier gaan ek net een skep, maar vir die res sal dit dieselfde wees. Ek gaan die verdeling deur nul breek. Soos u wel weet in die wiskunde, kan 'n getal nie gedeel word deur 0. As dit in die verwerker gebeur, word 'n uitsondering gegenereer omdat dit nie kan voortgaan nie. In IDT stem die eerste onderbreking in lys (0) ooreen met hierdie gebeurtenis.
Ons voeg dit by tussen die geheue-instelling en die spoel binne die Install-funksie van die IDT:
ND::IDT::SetGate(0,(unsigned)ND::ISR::ISR1,0x08,0x8E);
Die terugbelfunksie is ND :: ISR :: ISR1, wat eenvoudig is, hoewel ons ASM moet gebruik:
void ND::ISR::ISR1()
{
asm volatile(
"cli \n"
"pushl 0 \n"
"pushl 0 \n"
"jmp ND_ISR_Common \n"
);
}
ND_ISR_Common sal ons dit definieer as 'n funksie in die taal C. Om lêers te stoor en die leesbaarheid te verbeter, kan ons eksterne «C» {} gebruik:
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"
);
}
Hierdie kode in ASM kan moeilik wees om te verstaan, maar dit is omdat ons 'n struktuur in C gaan verklaar om toegang te verkry tot die data wat deur die onderbreking gegenereer word. As u dit nie wil hê nie, kan u natuurlik die Kernel Panic in ND :: ISR :: ISR1 of iets dergeliks bel. Die struktuur het so 'n vorm dat:
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;
};
En uiteindelik maak ons die ND_ISR_Handler-funksie (ook met 'n C-skakel) waarin ons 'n kernpaniek en 'n klein beskrywing van die fout toon volgens die een wat ons in 'n lys van foute het.
extern "C"
void ND_ISR_Handler(struct regs *r)
{
if(r->int_no < 32) { ND::Panic::Show(exception_messages[r->int_no]);
for(;;);
}
}
Goed en hiermee kan ons hierdie onderbreking al hanteer. Met die res van onderbrekings sou dit soortgelyk gebeur, behalwe dat daar sommige is wat parameters teruggee en dat ons die regstruktuur sou gebruik om dit te verkry. U kan egter wonder hoe ons weet of dit regtig werk. Om te toets of dit werk, gaan ons 'n eenvoudige lyn na die ND :: IDT :: Install () bekendstel:
int sum=10/0;
As ons dit saamstel, sal dit ons 'n waarskuwing gee en as ons dit probeer uitvoer, sal ons 'n mooi skerm kry:
En hiermee eindig hierdie pos, ek dink dit is een van die mees uitgebreide, maar baie funksionele.
5 kommentaar, los joune
Ek het oorgeskakel na LFS, dit is meer aaneenlopend.
Heilig ... In elk geval, die tutoriale is goed.
Baie goed, ek het dit van die begin af gevolg. Kan u die kodes aan elke sleepwa heg?
U het al die bronkode beskikbaar op GitHub: http://github.com/AdrianArroyoCalle/next-divel Van daar af kan u 'n ZIP, 'n TAR.GZ aflaai of net git gebruik.
Hahaha baie goed! Goedkeur! 🙂