Угледање на Линуса Торвалдса: Креирајте свој оперативни систем од 0 (В)

У овом петом делу видећемо табелу прилично сличну ГДТ-у и у теорији и у употреби, позивамо се на ИДТ. ИДТ је скраћеница за Табела описа прекида и је табела која се користи за обраду насталих прекида. На пример, неко направи дељење са 0, позива се функција задужена за обраду. Ове функције су ИСР (Рутине услуга прекида). Па хајде да креирамо ИДТ и додамо неки ИСР.

Прво ћемо прогласити структуре које одговарају ИДТ-у:

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

Као што се може видети ако га упоредите са ГДТ-ом, Птр структура је идентична, а Ентри је прилично слична. Стога су функције стављања уноса (СетГате) и инсталирања (Инсталл) врло сличне.

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

Инсталирај:

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

Ако погледамо, видећемо да функција инсталирања користи функцију НД :: Мемори :: Сет коју смо декларисали у другом посту. Такође можемо видети како још увек не упућујемо позиве СетГате-у и позивамо НД :: ИДТ :: Флусх, за ову функцију поново користимо асм волатиле израз:

asm volatile("lidtl (idtptr)");

Ако све буде у реду и направимо естетски аранжман, то би требало да изгледа овако:

НектДивел-ИДТ

У реду, сада ћемо почети да испуњавамо ИДТ прекидима. Овде ћу створити само један, али у осталом би то било исто. Учинићу поделу са нулом прекида. Као што знате из математике, број се не може делити са 0. Ако се то догоди у процесору, генерише се изузетак јер не може да се настави. У ИДТ-у први прекид на листи (0) одговара овом догађају.

Ово додајемо између поставке меморије и испирања у оквиру функције Инсталирање ИДТ-а:

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

Функција повратног позива биће НД :: ИСР :: ИСР1 што је прилично једноставно иако морамо користити АСМ:

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

Дефинисаћемо НД_ИСР_Цоммон као функцију на језику Ц. Да бисмо сачували датотеке и побољшали читљивост, можемо користити екстерни „Ц“ {}:

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

Овај код у АСМ-у може бити мало тежак за разумевање, али то је зато што ћемо прогласити структуру у Ц-у за приступ подацима генерисаним прекидом. Очигледно, ако то нисте желели, можете једноставно назвати Кернел Паниц у НД :: ИСР :: ИСР1 или нешто слично. Конструкција има такав облик да:

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

И на крају радимо функцију НД_ИСР_Хандлер (такође са Ц везом) у којој показујемо панику језгра и мали опис грешке према оној коју имамо на листи грешака.

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

Добро, и овим смо већ у стању да се носимо са овим прекидом. Са осталим прекидима би се догодило слично, осим што постоје неки који враћају параметре и ми бисмо користили рег структуру да бисмо их добили. Међутим, можда се питате како знамо да ли то заиста функционише. Да бисмо тестирали да ли ради, увешћемо једноставну линију након НД :: ИДТ :: Инсталл ():

int sum=10/0;

Ако компајлирамо, даће нам упозорење и ако покушамо да га извршимо, добићемо леп екран:

НектДивел-ИСР


И овим се завршава овај пост, мислим да је један од најопсежнијих, али прилично функционалан.


Оставите свој коментар

Ваша емаил адреса неће бити објављена. Обавезна поља су означена са *

*

*

  1. За податке одговоран: Мигуел Ангел Гатон
  2. Сврха података: Контрола нежељене поште, управљање коментарима.
  3. Легитимација: Ваш пристанак
  4. Комуникација података: Подаци се неће преносити трећим лицима, осим по законској обавези.
  5. Похрана података: База података коју хостује Оццентус Нетворкс (ЕУ)
  6. Права: У било ком тренутку можете ограничити, опоравити и избрисати своје податке.

  1.   Месодаблер дијо

    Отишао сам на ЛФС, то је континуираније.

  2.   елиотиме3000 дијо

    Свето ... У сваком случају, туторијали су добри.

  3.   sc дијо

    Врло добро, пратим га од почетка. Можете ли да приложите кодове свакој приколици?

    1.    АдрианАрроиоСтреет дијо

      На ГитХуб-у имате доступан сав изворни код: http://github.com/AdrianArroyoCalle/next-divel Одатле можете преузети ЗИП, ТАР.ГЗ или једноставно користити гит.

  4.   нијансиран дијо

    Хахаха врло добро! Одобри! 🙂