Получается у меня есть ОС, но после добавления IDT и GDT она перестала запускаться на Virtual Box, и от безысходности решил попробовать запустить на QEMU, и всё заработало. Как так? Я бы оставил ссылку на репозиторий, но он пока что закрыт, так что если нужен код других файлов - говорите
IDT.cpp:
#include "IDT/IDT.h"
#include "terminal/terminal.h"
#include "utils/utils.h"
using namespace SimpleOS;
void IDT::init_idt() {
idt_ptr.limit = (sizeof(struct IDTSlot) * IDT_SIZE) - 1;
idt_ptr.base = (uintptr_t)&idt;
memset(&idt, 0, sizeof(struct IDTSlot) * IDT_SIZE);
load_idt();
for(size_t i = 0; i < 32; ++i) {
set_in_idt_slot(i, (uint32_t)dividing_by_zero, 0x08, 0x8E);
}
}
void IDT::set_in_idt_slot(int pos, uint32_t base, uint16_t sel, uint8_t flags) {
idt[pos].offset_first = base & 0xFFFF;
idt[pos].selector = sel;
idt[pos].zero = 0;
idt[pos].type_attr = flags | 0x60;
idt[pos].offset_second = (base >> 16) & 0xFFFF;
}
extern "C" void SimpleOS::dividing_by_zero() {
Terminal::print("Failed operation dividing by zero");
}
IDT::IDTSlot IDT::idt[IDT_SIZE];
IDT::IDTPtr IDT::idt_ptr;
GDT.cpp:
#include "GDT/GDT.h"
#include "utils/utils.h"
using namespace SimpleOS;
void GDT::init_gdt() {
gdt_ptr.limit = (sizeof(struct GDTSlot) * 6) - 1;
gdt_ptr.base = (unsigned int)&gdt;
set_in_gdt_slot(0, 0, 0, 0, 0);
set_in_gdt_slot(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
set_in_gdt_slot(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
set_in_gdt_slot(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
set_in_gdt_slot(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
write_tss(5, 0x10, 0x0);
load_gdt();
load_tss();
}
void GDT::set_in_gdt_slot(int pos, uint64_t base, uint64_t limit, uint8_t access, uint8_t gran) {
gdt[pos].base_low = (base & 0xFFFF);
gdt[pos].base_middle = (base >> 16) & 0xFF;
gdt[pos].base_high = (base >> 24) & 0xFF;
gdt[pos].limit_low = (limit & 0xFFFF);
gdt[pos].granularity = (limit >> 16) & 0X0F;
gdt[pos].granularity |= (gran & 0xF0);
gdt[pos].access = access;
}
void GDT::write_tss(int32_t pos, uint16_t ss0, uint32_t esp0) {
uintptr_t base = (uintptr_t)&tss_entry;
uintptr_t limit = base + sizeof(tss_entry);
set_in_gdt_slot(pos, base, limit, 0xE9, 0x00);
memset(&tss_entry, 0x0, sizeof(tss_entry));
tss_entry.ss0 = ss0;
tss_entry.esp0 = esp0;
tss_entry.cs = 0x0b;
tss_entry.ss =
tss_entry.ds =
tss_entry.es =
tss_entry.fs =
tss_entry.gs = 0x13;
tss_entry.iomap_base = sizeof(tss_entry);
}
GDT::GDTSlot GDT::gdt[6];
GDT::GDTPtr GDT::gdt_ptr;
GDT::tss_entry_t GDT::tss_entry;