Pada angsuran kelima ini kita akan melihat tabel yang sangat mirip dengan GDT baik secara teori maupun dalam penggunaannya, kita mengacu pada IDT. IDT adalah singkatan dari Tabel Deskripsi Interupsi y adalah tabel yang digunakan untuk menangani interupsi yang terjadi. Misalnya, seseorang membuat pembagian dengan 0, fungsi yang bertanggung jawab atas pemrosesan disebut. Fungsi-fungsi ini adalah ISR (Rutinitas Layanan Interupsi). Jadi mari buat IDT dan tambahkan beberapa ISR.
Pertama kita akan mendeklarasikan struktur yang sesuai dengan 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));
Seperti yang dapat dilihat jika Anda membandingkannya dengan GDT, struktur Ptr identik dan Entri sangat mirip. Oleh karena itu, fungsi meletakkan entri (SetGate) dan menginstal (Instal) sangat mirip.
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;
}
Install:
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();
Jika kita perhatikan, kita akan melihat bahwa fungsi install menggunakan fungsi ND :: Memory :: Set yang telah kita deklarasikan di posting lain. Kami juga menghargai bagaimana kami belum melakukan panggilan ke SetGate dan kami memanggil ND :: IDT :: Flush, untuk fungsi ini kami menggunakan pernyataan volatile asm lagi:
asm volatile("lidtl (idtptr)");
Jika semuanya berjalan dengan baik dan kita membuat tatanan estetika maka akan terlihat seperti ini:
Oke, sekarang mari mulai mengisi RTD dengan interupsi. Di sini saya akan membuat hanya satu tetapi sisanya akan sama. Saya akan melakukan pembagian dengan istirahat nol. Seperti yang Anda ketahui dalam matematika, bilangan tidak dapat dibagi dengan 0. Jika ini terjadi di prosesor, pengecualian akan dibuat karena tidak dapat dilanjutkan. Dalam IDT, interupsi pertama dalam daftar (0) berhubungan dengan peristiwa ini.
Kami menambahkan ini antara pengaturan memori dan flush dalam fungsi Instal IDT:
ND::IDT::SetGate(0,(unsigned)ND::ISR::ISR1,0x08,0x8E);
Fungsi callback akan menjadi ND :: ISR :: ISR1 yang cukup sederhana meskipun kita harus menggunakan ASM:
void ND::ISR::ISR1()
{
asm volatile(
"cli \n"
"pushl 0 \n"
"pushl 0 \n"
"jmp ND_ISR_Common \n"
);
}
ND_ISR_Common kita akan mendefinisikannya sebagai fungsi dalam bahasa C. Untuk menyimpan file dan meningkatkan keterbacaan kita bisa menggunakan extern «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"
);
}
Kode dalam ASM ini bisa sedikit sulit untuk dipahami tetapi ini karena kita akan mendeklarasikan struktur di C untuk mengakses data yang dihasilkan oleh interupsi. Tentunya, jika Anda tidak menginginkannya, Anda bisa memanggil Kernel Panic di ND :: ISR :: ISR1 atau semacamnya. Bentuk strukturnya sedemikian rupa sehingga:
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;
};
Dan terakhir kami melakukan fungsi ND_ISR_Handler (juga dengan tautan C) di mana kami menunjukkan kepanikan kernel dan deskripsi kecil tentang kesalahan sesuai dengan yang kami miliki di daftar kesalahan.
extern "C"
void ND_ISR_Handler(struct regs *r)
{
if(r->int_no < 32) { ND::Panic::Show(exception_messages[r->int_no]);
for(;;);
}
}
Bagus dan dengan ini kami sudah bisa menangani gangguan ini. Dengan sisa interupsi, itu akan terjadi serupa kecuali bahwa ada beberapa yang mengembalikan parameter dan kami akan menggunakan struktur reg untuk mendapatkannya. Namun, Anda mungkin bertanya-tanya bagaimana kami tahu apakah itu benar-benar berhasil. Untuk menguji apakah berhasil, kita akan memperkenalkan baris sederhana setelah ND :: IDT :: Install ():
int sum=10/0;
Jika kita mengkompilasinya akan memberi kita peringatan dan jika kita mencoba menjalankannya kita akan mendapatkan layar yang bagus:
Dan dengan ini berakhirnya posting ini, saya pikir ini adalah salah satu yang paling luas tetapi cukup fungsional.
Saya pergi ke LFS, itu lebih berkelanjutan.
Astaga ... Bagaimanapun, tutorialnya bagus.
Bagus sekali, saya sudah mengikutinya dari awal. Bisakah Anda melampirkan kode ke setiap trailer?
Anda memiliki semua kode sumber yang tersedia di GitHub: http://github.com/AdrianArroyoCalle/next-divel Dari sana Anda dapat mengunduh ZIP, TAR.GZ atau cukup gunakan git.
Hahaha sangat bagus! Menyetujui! 🙂