Efterligne Linus Torvalds: Opret dit eget operativsystem fra 0 (V)

I denne femte rate vil vi se en tabel, der ligner GDT både i teori og i brug, vi henviser til IDT. IDT står for Afbrydelse af tabellen Beskrivelse y er en tabel, der bruges til at håndtere afbrydelser, der opstår. For eksempel laver nogen en division med 0, den funktion, der er ansvarlig for behandlingen, kaldes. Disse funktioner er ISR (Afbryd servicerutiner). Så lad os oprette IDT og tilføje noget ISR.

Først skal vi erklære de strukturer, der svarer til 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));

Som det kan ses, hvis du sammenligner det med GDT, er Ptr-strukturen identisk, og indgangen er ret ens. Derfor er funktionerne for at placere en post (SetGate) og installere (Install) meget ens.

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

Installere:

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

Hvis vi ser, vil vi se, at installationsfunktionen bruger ND :: Memory :: Set-funktionen, som vi havde erklæret i det andet indlæg. Vi kan også sætte pris på, hvordan vi endnu ikke foretager opkald til SetGate, og vi kalder ND :: IDT :: Flush, til denne funktion bruger vi asm-flygtige udsagn igen:

asm volatile("lidtl (idtptr)");

Hvis alt går godt, og vi laver et æstetisk arrangement, skal det se sådan ud:

NæsteDivel-IDT

Okay, nu skal vi begynde at udfylde IDT med afbrydelser. Her vil jeg kun oprette en, men for resten ville det være det samme. Jeg vil dele med nul pause. Som du godt ved i matematik, kan et tal ikke deles med 0. Hvis dette sker i processoren, genereres en undtagelse, da det ikke kan fortsætte. I IDT svarer den første afbrydelse i listen (0) til denne begivenhed.

Vi tilføjer dette mellem hukommelsesindstillingen og skylningen inden for IDT's installationsfunktion:

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

Tilbagekaldsfunktionen bliver ND :: ISR :: ISR1, hvilket er ret simpelt, selvom vi skal bruge ASM:

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

ND_ISR_Common definerer vi det som en funktion på sprog C. For at gemme filer og forbedre læsbarheden kan vi bruge ekstern «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"
);
}

Denne kode i ASM kan være lidt vanskelig at forstå, men det er fordi vi vil erklære en struktur i C for at få adgang til de data, der genereres af afbrydelsen. Hvis du ikke ønsker det, kan du naturligvis bare ringe til Kernel Panic i ND :: ISR :: ISR1 eller noget lignende. Strukturen har en sådan form, at:

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

Og til sidst laver vi ND_ISR_Handler-funktionen (også med et C-link), hvor vi viser en kernepanik og en lille beskrivelse af fejlen i henhold til den, vi har i en liste over fejl.

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

Godt og med dette er vi allerede i stand til at håndtere denne afbrydelse. Med resten af ​​afbrydelser ville det ske ens, bortset fra at der er nogle, der returnerer parametre, og vi ville bruge reg-strukturen til at opnå det. Du kan dog undre dig over, hvordan vi ved, om det virkelig fungerer. For at teste om det fungerer, introducerer vi en simpel linje efter ND :: IDT :: Install ():

int sum=10/0;

Hvis vi kompilerer, giver det os en advarsel, og hvis vi prøver at udføre det, får vi en flot skærm:

NæsteDivel-ISR
Og med dette slutter dette indlæg, jeg synes, det er et af de mest omfattende, men ret funktionelle.


Indholdet af artiklen overholder vores principper for redaktionel etik. Klik på for at rapportere en fejl her.

5 kommentarer, lad dine

Efterlad din kommentar

Din e-mailadresse vil ikke blive offentliggjort.

*

*

  1. Ansvarlig for dataene: Miguel Ángel Gatón
  2. Formålet med dataene: Control SPAM, management af kommentarer.
  3. Legitimering: Dit samtykke
  4. Kommunikation af dataene: Dataene vil ikke blive kommunikeret til tredjemand, undtagen ved juridisk forpligtelse.
  5. Datalagring: Database hostet af Occentus Networks (EU)
  6. Rettigheder: Du kan til enhver tid begrænse, gendanne og slette dine oplysninger.

  1.   mesodabler sagde han

    Jeg skiftede til LFS, det er mere kontinuerligt.

  2.   eliotime3000 sagde han

    Hellig ... Under alle omstændigheder er selvstudierne gode.

  3.   sc sagde han

    Meget god, jeg har fulgt det fra starten. Kunne du vedhæfte koderne til hver trailer?

    1.    AdrianArroyoStreet sagde han

      Du har al kildekoden tilgængelig på GitHub: http://github.com/AdrianArroyoCalle/next-divel Derfra kan du downloade en ZIP, en TAR.GZ eller bare bruge git.

  4.   nuanceret sagde han

    Hahaha meget godt! Godkende! 🙂