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

Pada ansuran kelima ini, kita akan melihat jadual yang hampir sama dengan GDT baik dari segi teori dan penggunaannya, kita merujuk kepada IDT. IDT bermaksud Jadual Huraian Gangguan y adalah jadual yang digunakan untuk menangani gangguan yang berlaku. Sebagai contoh, seseorang membuat pembahagian dengan 0, fungsi yang bertanggungjawab untuk pemprosesan disebut. Fungsi-fungsi ini adalah ISR (Ganggu Rutin Perkhidmatan). Oleh itu mari kita buat IDT dan tambahkan beberapa ISR.

Mula-mula kita akan menyatakan 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 adalah serupa dan Entri agak serupa. Oleh itu fungsi meletakkan entri (SetGate) dan memasang (Pasang) sangat serupa.

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

Pasang:

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

Sekiranya kita melihat, kita akan melihat bahawa fungsi pemasangan menggunakan fungsi ND :: Memory :: Set yang telah kita nyatakan di post yang lain. Kita juga dapat melihat bagaimana kita belum membuat panggilan ke SetGate dan kita memanggil ND :: IDT :: Flush, untuk fungsi ini kita menggunakan pernyataan volatile asm sekali lagi:

asm volatile("lidtl (idtptr)");

Sekiranya semuanya berjalan lancar dan kami membuat susunan estetik, ia akan kelihatan seperti ini:

NextDivel-RTD

Baiklah, sekarang kita akan mula mengisi IDT dengan gangguan. Di sini saya akan membuat satu sahaja tetapi selebihnya ia akan sama. Saya akan melakukan pembahagian dengan rehat sifar. Seperti yang anda ketahui dalam matematik, nombor tidak dapat dibahagi dengan 0. Sekiranya ini berlaku dalam prosesor, pengecualian dihasilkan kerana tidak dapat diteruskan. Di IDT gangguan pertama dalam senarai (0) sesuai dengan peristiwa ini.

Kami menambahkan ini antara pengaturan memori dan pemisahan dalam fungsi Pasang IDT:

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

Fungsi panggil balik akan menjadi ND :: ISR :: ISR1 yang cukup mudah walaupun kita mesti 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 fail dan meningkatkan keterbacaan kita boleh menggunakan «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"
);
}

Kod ini di ASM sedikit sukar untuk dimengerti tetapi ini kerana kita akan menyatakan struktur di C untuk mengakses data yang dihasilkan oleh gangguan tersebut. Jelas sekali, jika anda tidak menginginkannya, anda boleh menghubungi Kernel Panic di ND :: ISR :: ISR1 atau seumpamanya. Strukturnya mempunyai bentuk seperti:

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 akhirnya kami melakukan fungsi ND_ISR_Handler (juga dengan pautan C) di mana kami menunjukkan kernel panik dan penerangan kecil mengenai kesalahan tersebut seperti yang kami ada dalam senarai 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 kita sudah dapat mengatasi gangguan ini. Dengan gangguan selebihnya, ia akan berlaku serupa kecuali ada beberapa parameter yang mengembalikan dan kami akan menggunakan struktur reg untuk mendapatkannya. Walau bagaimanapun, anda mungkin tertanya-tanya bagaimana kita tahu jika ia benar-benar berfungsi. Untuk menguji sama ada ia berfungsi, kita akan memperkenalkan garis mudah selepas ND :: IDT :: Install ():

int sum=10/0;

Sekiranya kita menyusunnya, itu akan memberi kita amaran dan jika kita berusaha untuk melaksanakannya, kita akan mendapat skrin yang bagus:

NextDivel-ISR


Dan dengan berakhirnya catatan ini, saya fikir ia adalah salah satu yang paling luas tetapi cukup berfungsi.


Tinggalkan komen anda

Alamat email anda tidak akan disiarkan. Ruangan yang diperlukan ditanda dengan *

*

*

  1. Bertanggungjawab atas data: Miguel Ángel Gatón
  2. Tujuan data: Mengendalikan SPAM, pengurusan komen.
  3. Perundangan: Persetujuan anda
  4. Komunikasi data: Data tidak akan disampaikan kepada pihak ketiga kecuali dengan kewajiban hukum.
  5. Penyimpanan data: Pangkalan data yang dihoskan oleh Occentus Networks (EU)
  6. Hak: Pada bila-bila masa anda boleh menghadkan, memulihkan dan menghapus maklumat anda.

  1.   mesodabler kata

    Saya pergi ke LFS, ia lebih berterusan.

  2.   eliotime3000 kata

    Suci ... Bagaimanapun, tutorialnya bagus.

  3.   sc kata

    Bagus sekali, saya sudah mengikutinya sejak awal. Bolehkah anda melampirkan kod ke setiap treler?

    1.    Jalan AdrianArroyo kata

      Anda mempunyai semua kod sumber yang ada di GitHub: http://github.com/AdrianArroyoCalle/next-divel Dari sana anda boleh memuat turun ZIP, TAR.GZ atau hanya menggunakan git.

  4.   bernuansa kata

    Hahaha sangat bagus! Terima! 🙂