Emulimi i Linus Torvalds: Krijoni sistemin tuaj operativ nga 0 (V)

Në këtë këst të pestë do të shohim një tabelë mjaft të ngjashme me DPT si në teori ashtu edhe në përdorim, ne i referohemi IDT. IDT qëndron për Ndërprerjet Tabela e përshkrimit y është një tabelë që përdoret për të trajtuar ndërprerjet që ndodhin. Për shembull, dikush bën një ndarje me 0, funksioni i ngarkuar me përpunimin quhet. Këto funksione janë ISR (Ndërpritni rutinat e shërbimit) Pra, le të krijojmë IDT dhe të shtojmë disa ISR.

Së pari ne do të deklarojmë strukturat që korrespondojnë me 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));

Siç mund të shihet nëse e krahasoni me GDT, struktura Ptr është identike dhe Hyrja është mjaft e ngjashme. Prandaj, funksionet e vendosjes së një hyrje (SetGate) dhe instalimit (Install) janë shumë të ngjashme.

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

Instaloni:

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

Nëse shikojmë do të shohim që funksioni i instalimit përdor funksionin ND :: Memory :: Vendosni që kishim deklaruar në postimin tjetër. Ne gjithashtu mund të shohim se si nuk bëjmë asnjë thirrje në SetGate dhe ne e quajmë ND :: IDT :: Flush, për këtë funksion ne përsëri përdorim deklaratën e paqëndrueshme asm:

asm volatile("lidtl (idtptr)");

Nëse gjithçka shkon mirë dhe ne bëjmë një rregullim estetik duhet të duket kështu:

NextDivel-RTD

Mirë, tani do të fillojmë të mbushim IDT me ndërprerje. Këtu do të krijoj vetëm një, por për pjesën tjetër do të ishte e njëjta gjë. Unë jam duke shkuar për të bërë ndarjen me pushim zero. Siç e dini mirë në matematikë, një numër nuk mund të ndahet me 0. Nëse kjo ndodh në procesor, gjenerohet një përjashtim pasi nuk mund të vazhdojë. Në IDT ndërprerja e parë në listë (0) korrespondon me këtë ngjarje.

Ne e shtojmë këtë midis cilësimit të kujtesës dhe skuqjes brenda funksionit Install të IDT:

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

Funksioni i kthimit do të jetë ND :: ISR :: ISR1 i cili është mjaft i thjeshtë edhe pse duhet të përdorim ASM:

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

ND_ISR_Common ne do ta përcaktojmë atë si një funksion në gjuhën C. Për të ruajtur skedarët dhe për të përmirësuar lexueshmërinë, ne mund të përdorim «C» të jashtëm {}:

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

Ky kod në ASM mund të jetë paksa i vështirë për tu kuptuar por kjo është për shkak se ne do të deklarojmë një strukturë në C për të hyrë në të dhënat e krijuara nga ndërprerja. Padyshim, nëse nuk e dëshironi atë, thjesht mund të telefononi Panikun e Kernelit në ND :: ISR :: ISR1 ose diçka e tillë. Struktura ka një formë të tillë që:

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

Dhe së fundmi ne bëjmë funksionin ND_ISR_Handler (gjithashtu me një lidhje C) në të cilin tregojmë një panik të kernelit dhe një përshkrim të vogël të gabimit sipas atij që kemi në një listë të gabimeve.

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

Mirë dhe me këtë ne tashmë jemi në gjendje ta trajtojmë këtë ndërprerje. Me pjesën tjetër të ndërprerjeve do të ndodhte e ngjashme përveç se ka disa që kthejnë parametrat dhe ne do të përdorim strukturën reg për ta marrë atë. Sidoqoftë, mund të pyesni veten se si e dimë nëse funksionon vërtet. Për të provuar nëse funksionon, ne do të prezantojmë një linjë të thjeshtë pas ND :: IDT :: Install ():

int sum=10/0;

Nëse përpilojmë do të na japë një paralajmërim dhe nëse përpiqemi ta ekzekutojmë atë do të kemi një ekran të këndshëm:

NextDivel-ISR


Dhe me këtë mbaron ky postim, mendoj se është një nga më të zgjeruarit, por mjaft funksional.


5 komente, lini tuajën

Lini komentin tuaj

Adresa juaj e emailit nuk do të publikohet. Fusha e kërkuar janë shënuar me *

*

*

  1. Përgjegjës për të dhënat: Miguel Ángel Gatón
  2. Qëllimi i të dhënave: Kontrolloni SPAM, menaxhimin e komenteve.
  3. Legjitimimi: Pëlqimi juaj
  4. Komunikimi i të dhënave: Të dhënat nuk do t'u komunikohen palëve të treta përveç me detyrim ligjor.
  5. Ruajtja e të dhënave: Baza e të dhënave e organizuar nga Occentus Networks (BE)
  6. Të drejtat: Në çdo kohë mund të kufizoni, rikuperoni dhe fshini informacionin tuaj.

  1.   mesodabler dijo

    Unë shkova në AFP, është më e vazhdueshme.

  2.   eliotime3000 dijo

    Shenjtë ... Gjithsesi, udhëzimet janë të mira.

  3.   sc dijo

    Shumë mirë, e kam ndjekur që nga fillimi. A mund t'i bashkangjitni kodet në secilën rimorkio?

    1.    AdrianArroyoStreet dijo

      Ju keni të gjithë kodin burimor të disponueshëm në GitHub: http://github.com/AdrianArroyoCalle/next-divel Nga atje mund të shkarkoni një ZIP, një TAR.GZ ose thjesht të përdorni git.

  4.   të nuancuar dijo

    Hahaha shume mire! Miratoni! 🙂