Linus Torvalds'ı Taklit Etme: 0 (V) 'den kendi işletim sisteminizi oluşturun

Bu beşinci bölümde hem teorik hem de kullanımda GDT'ye oldukça benzer bir tablo göreceğiz, IDT'ye atıfta bulunacağız. IDT, Kesmeler Açıklama Tablosu y, meydana gelen kesintileri işlemek için kullanılan bir tablodur. Örneğin, birisi 0'a bölme yapar, işlemden sorumlu fonksiyon çağrılır. Bu işlevler ISR'dir (Hizmet Rutinlerini Kes). Öyleyse IDT oluşturalım ve biraz ISR ekleyelim.

Önce IDT'ye karşılık gelen yapıları açıklayacağız:

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

Görüldüğü gibi GDT ile karşılaştırırsanız, Ptr yapısı aynıdır ve Giriş oldukça benzerdir. Bu nedenle, bir girdi koyma (SetGate) ve yükleme (Kur) işlevleri çok benzerdir.

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

Yüklemek:

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

Bakarsak, yükleme işlevinin diğer yazıda bildirmiş olduğumuz ND :: Memory :: Set işlevini kullandığını göreceğiz. SetGate'e henüz nasıl çağrı yapmadığımızı da görebiliriz ve ND :: IDT :: Flush diyoruz, bu fonksiyon için asm volatile ifadesini tekrar kullanıyoruz:

asm volatile("lidtl (idtptr)");

Her şey yolunda giderse ve estetik bir düzenleme yaparsak şöyle görünmeli:

SonrakiDive-IDT

Tamam, şimdi IDT'yi kesintilerle doldurmaya başlayacağız. Burada sadece bir tane yaratacağım ama geri kalanı için aynı olacak. Sıfıra bölme işlemini yapacağım. Matematikte bildiğiniz gibi, bir sayı 0'a bölünemez. Bu işlemcide olursa, devam edemeyeceği için bir istisna oluşturulur. IDT'de (0) listesindeki ilk kesinti bu olaya karşılık gelir.

Bunu, IDT'nin Kurulum işlevi içindeki bellek ayarı ve yıkama arasına ekliyoruz:

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

Geri çağırma işlevi ND :: ISR :: ISR1 olacaktır ki bu oldukça basittir, ancak ASM kullanmamız gerekir:

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

ND_ISR_Common'u C dilinde bir işlev olarak tanımlayacağız. Dosyaları kaydetmek ve okunabilirliği artırmak için extern "C" {} kullanabiliriz:

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

ASM'deki bu kodun anlaşılması biraz zor olabilir, ancak bunun nedeni, kesme tarafından üretilen verilere erişmek için C'de bir yapı tanımlayacağız. Açıkçası, eğer bunu istemediyseniz, Kernel Panic'i ND :: ISR :: ISR1 veya bunun gibi bir şeyden çağırabilirsiniz. Yapının şekli şu şekildedir:

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

Ve son olarak ND_ISR_Handler işlevini (ayrıca bir C bağlantısıyla) yaparız, burada bir çekirdek paniği ve bir hata listesinde sahip olduğumuza göre hatanın küçük bir açıklaması gösterilir.

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

Güzel ve bununla bu kesintiyi şimdiden halledebiliyoruz. Geri kalan kesintilerde, parametreler döndüren bazılarının olması ve bunu elde etmek için reg yapısını kullanmamız dışında benzer olur. Ancak, gerçekten işe yarayıp yaramadığını nasıl bildiğimizi merak edebilirsiniz. Çalışıp çalışmadığını test etmek için ND :: IDT :: Install () 'dan sonra basit bir satır ekleyeceğiz:

int sum=10/0;

Derlersek bize bir uyarı verecek ve çalıştırmaya çalışırsak güzel bir ekran alacağız:

SonrakiDivel-ISR


Ve bu yazının sonunda, bence en kapsamlı ama oldukça işlevsel olanlardan biri.


5 yorum, sizinkini bırakın

Yorumunuzu bırakın

E-posta hesabınız yayınlanmayacak. Gerekli alanlar ile işaretlenmiştir *

*

*

  1. Verilerden sorumlu: Miguel Ángel Gatón
  2. Verilerin amacı: Kontrol SPAM, yorum yönetimi.
  3. Meşruiyet: Onayınız
  4. Verilerin iletilmesi: Veriler, yasal zorunluluk dışında üçüncü kişilere iletilmeyecektir.
  5. Veri depolama: Occentus Networks (AB) tarafından barındırılan veritabanı
  6. Haklar: Bilgilerinizi istediğiniz zaman sınırlayabilir, kurtarabilir ve silebilirsiniz.

  1.   mesodabler dijo

    LFS'ye gittim, daha sürekli.

  2.   eliotime3000 dijo

    Kutsal ... Her neyse, öğreticiler iyi.

  3.   sc dijo

    Çok güzel, başından beri takip ediyorum. Kodları her bir fragmana ekleyebilir misiniz?

    1.    AdrianArroyoSokak dijo

      GitHub'da bulunan tüm kaynak koduna sahipsiniz: http://github.com/AdrianArroyoCalle/next-divel Oradan bir ZIP, bir TAR.GZ indirebilir veya sadece git'i kullanabilirsiniz.

  4.   detaylı dijo

    Hahaha çok iyi! Onaylayın! 🙂