Meniru Linus Torvalds: Buat sistem operasi Anda sendiri dari 0 (V)

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:

BerikutnyaDivel-IDT

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:

BerikutnyaDivel-ISR


Dan dengan ini berakhirnya posting ini, saya pikir ini adalah salah satu yang paling luas tetapi cukup fungsional.


tinggalkan Komentar Anda

Alamat email Anda tidak akan dipublikasikan. Bidang yang harus diisi ditandai dengan *

*

*

  1. Penanggung jawab data: Miguel Ángel Gatón
  2. Tujuan data: Mengontrol SPAM, manajemen komentar.
  3. Legitimasi: Persetujuan Anda
  4. Komunikasi data: Data tidak akan dikomunikasikan kepada pihak ketiga kecuali dengan kewajiban hukum.
  5. Penyimpanan data: Basis data dihosting oleh Occentus Networks (UE)
  6. Hak: Anda dapat membatasi, memulihkan, dan menghapus informasi Anda kapan saja.

  1.   mesodabler dijo

    Saya pergi ke LFS, itu lebih berkelanjutan.

  2.   eliotime3000 dijo

    Astaga ... Bagaimanapun, tutorialnya bagus.

  3.   sc dijo

    Bagus sekali, saya sudah mengikutinya dari awal. Bisakah Anda melampirkan kode ke setiap trailer?

    1.    AdrianArroyoStreet dijo

      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.

  4.   bernuansa dijo

    Hahaha sangat bagus! Menyetujui! 🙂