Linus Torvalds emuleren: maak uw eigen besturingssysteem van 0 (V)

In deze vijfde aflevering zullen we een tabel zien die sterk lijkt op de GDT, zowel in theorie als in gebruik, we verwijzen naar de IDT. IDT staat voor Onderbreekt Beschrijving Tabel y is een tabel die wordt gebruikt om interrupts af te handelen. Iemand maakt bijvoorbeeld een deling door 0, de functie die verantwoordelijk is voor de verwerking wordt genoemd. Deze functies zijn de ISR (Serviceroutines onderbreken). Dus laten we de IDT maken en wat ISR toevoegen.

Eerst gaan we de structuren declareren die overeenkomen met de 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));

Zoals je kunt zien als je het vergelijkt met de GDT, is de Ptr-structuur identiek en is de invoer vrij gelijkaardig. Daarom lijken de functies van het plaatsen van een item (SetGate) en het installeren (Installeren) sterk op elkaar.

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

Installeren:

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

Als we kijken, zullen we zien dat de install-functie de functie ND :: Memory :: Set gebruikt die we in het andere bericht hadden gedeclareerd. We kunnen ook waarderen dat we nog geen oproepen doen naar SetGate en we noemen ND :: IDT :: Flush, voor deze functie gebruiken we opnieuw de asm vluchtige instructie:

asm volatile("lidtl (idtptr)");

Als alles goed gaat en we een esthetisch arrangement maken, zou het er als volgt uit moeten zien:

VolgendeDivel-IDT

Oké, nu gaan we beginnen met het vullen van de IDT met interrupts. Hier ga ik er maar één maken, maar voor de rest zou het hetzelfde zijn. Ik ga de pauze delen door nul. Zoals je in de wiskunde goed weet, kan een getal niet worden gedeeld door 0. Als dit in de processor gebeurt, wordt er een uitzondering gegenereerd omdat deze niet kan doorgaan. In IDT komt de eerste interrupt in lijst (0) overeen met deze gebeurtenis.

We voegen dit toe tussen de geheugeninstelling en de spoeling binnen de installatiefunctie van de IDT:

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

De callback-functie wordt ND :: ISR :: ISR1, wat vrij eenvoudig is, hoewel we ASM moeten gebruiken:

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

ND_ISR_Common zullen we het definiëren als een functie in C-taal. Om bestanden op te slaan en de leesbaarheid te verbeteren, kunnen we externe «C» {} gebruiken:

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

Deze code in ASM kan een beetje moeilijk te begrijpen zijn, maar dit komt omdat we een structuur in C gaan declareren om toegang te krijgen tot de gegevens die door de interrupt worden gegenereerd. Als je dat niet wilde, zou je natuurlijk de Kernel Panic in ND :: ISR :: ISR1 of iets dergelijks kunnen bellen. De structuur heeft een zodanige 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 tot slot maken we de functie ND_ISR_Handler (ook met een C-link) waarin we een kernel panic en een kleine beschrijving van de fout laten zien volgens degene die we hebben in een lijst met fouten.

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 kunnen we deze onderbreking al opvangen. Met de rest van de onderbrekingen zou het hetzelfde gebeuren, behalve dat er enkele zijn die parameters retourneren en we zouden de reg-structuur gebruiken om het te verkrijgen. U kunt zich echter afvragen hoe we weten of het echt werkt. Om te testen of het werkt, gaan we een eenvoudige regel introduceren na de ND :: IDT :: Install ():

int sum=10/0;

Als we het compileren, krijgen we een waarschuwing en als we het proberen uit te voeren, krijgen we een mooi scherm:

VolgendeDivel-ISR


En hiermee eindigt dit bericht, ik denk dat het een van de meest uitgebreide maar best functionele is.


Laat je reactie achter

Uw e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd met *

*

*

  1. Verantwoordelijk voor de gegevens: Miguel Ángel Gatón
  2. Doel van de gegevens: Controle SPAM, commentaarbeheer.
  3. Legitimatie: uw toestemming
  4. Mededeling van de gegevens: De gegevens worden niet aan derden meegedeeld, behalve op grond van wettelijke verplichting.
  5. Gegevensopslag: database gehost door Occentus Networks (EU)
  6. Rechten: u kunt uw gegevens op elk moment beperken, herstellen en verwijderen.

  1.   mesodabler zei

    Ik ben overgestapt op LFS, het is meer continu.

  2.   eliotime3000 zei

    Heilig ... Hoe dan ook, de tutorials zijn goed.

  3.   sc zei

    Heel goed, ik heb het vanaf het begin gevolgd. Kunt u de codes aan elke trailer koppelen?

    1.    AdrianArroyoStreet zei

      Je hebt alle broncode beschikbaar op GitHub: http://github.com/AdrianArroyoCalle/next-divel Van daaruit kun je een ZIP, een TAR.GZ downloaden of gewoon git gebruiken.

  4.   genuanceerd zei

    Hahaha erg goed! Goedkeuren! 🙂