Емуляція Лінуса Торвальда: Створіть власну операційну систему з нуля (VI)

Ну, після невеликої дужки ми продовжуємо з нашою серією навчальних посібників. Якщо ми повернемося до попереднього коду, ми повинні мати ISR ділення на нуль. Тепер ми повинні заповнити решту ISR, для яких ми розмістили повідомлення (перші 32). Ну, зараз ми будемо продовжувати переривання програмування, ми будемо робити IRQ, також відомі як Запити на переривання. Ці IRQ генеруються апаратними пристроями, такими як клавіатури, миші, принтери тощо. Спочатку перші 8 IRQ автоматично відображаються у позиціях IDT з 8 по 15. Оскільки ми використовували перші 32 для винятків, то тепер їх доводиться переназначати. Ми встановимо IRQ з 32 на 45. Для цього ми повинні спочатку переназначити IRQ:

void ND::IRQ::Remap(int pic1, int pic2)
{
#define PIC1 0x20
#define PIC2 0xA0
#define ICW1 0x11
#define ICW4 0x01
/* send ICW1 */
ND::Ports::OutputB(PIC1, ICW1);
ND::Ports::OutputB(PIC2, ICW1);
/* send ICW2 */
ND::Ports::OutputB(PIC1 + 1, pic1); /* remap */
ND::Ports::OutputB(PIC2 + 1, pic2); /* pics */
/* send ICW3 */
ND::Ports::OutputB(PIC1 + 1, 4); /* IRQ2 -> connection to slave */
ND::Ports::OutputB(PIC2 + 1, 2);
/* send ICW4 */
ND::Ports::OutputB(PIC1 + 1, ICW4);
ND::Ports::OutputB(PIC2 + 1, ICW4);
/* disable all IRQs */
ND::Ports::OutputB(PIC1 + 1, 0xFF);
}

Тепер ми створюємо функцію для встановлення IRQ:

void ND::IRQ::Install()
{
ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_BLACK);
ND::Screen::PutString("\nInstalling IRQ...");
ND::IRQ::Remap(0x20,0x28);
ND::IDT::SetGate(32,(unsigned)ND::IRQ::IRQ1,0x08,0x8E);
ND::IDT::SetGate(33,(unsigned)ND::IRQ::IRQ2,0x08,0x8E);
ND::IDT::SetGate(34,(unsigned)ND::IRQ::IRQ3,0x08,0x8E);
ND::IDT::SetGate(35,(unsigned)ND::IRQ::IRQ4,0x08,0x8E);
ND::IDT::SetGate(36,(unsigned)ND::IRQ::IRQ5,0x08,0x8E);
ND::IDT::SetGate(37,(unsigned)ND::IRQ::IRQ6,0x08,0x8E);
ND::IDT::SetGate(38,(unsigned)ND::IRQ::IRQ7,0x08,0x8E);
ND::IDT::SetGate(39,(unsigned)ND::IRQ::IRQ8,0x08,0x8E);
ND::IDT::SetGate(40,(unsigned)ND::IRQ::IRQ9,0x08,0x8E);
ND::IDT::SetGate(41,(unsigned)ND::IRQ::IRQ10,0x08,0x8E);
ND::IDT::SetGate(42,(unsigned)ND::IRQ::IRQ11,0x08,0x8E);
ND::IDT::SetGate(43,(unsigned)ND::IRQ::IRQ12,0x08,0x8E);
ND::IDT::SetGate(44,(unsigned)ND::IRQ::IRQ13,0x08,0x8E);
ND::IDT::SetGate(45,(unsigned)ND::IRQ::IRQ14,0x08,0x8E);
ND::IDT::SetGate(46,(unsigned)ND::IRQ::IRQ15,0x08,0x8E);
ND::IDT::SetGate(47,(unsigned)ND::IRQ::IRQ16,0x08,0x8E);
ND::Screen::SetColor(ND_SIDE_FOREGROUND,ND_COLOR_GREEN);
ND::Screen::PutString("done");
asm volatile("sti");
}

Вирок asm сти ми активуємо IRQ. Ну, тепер ми йдемо з чимось схожим на ISR. Функції базового IRQ:

void ND::IRQ::IRQ1()
{
asm volatile(
"cli \n"
"pushl 0\n"
"pushl 32\n"
"jmp ND_IRQ_Common"
);
}

Загальна частина (така ж, як ISR):

extern "C"
void ND_IRQ_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_IRQ_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"
);
}

І основний обробник:

extern "C"
void ND_IRQ_Handler(struct regs* r)
{
void (*handler)(struct regs *r);
if(r->int_no >= 40)
{
ND::Ports::OutputB(0xA0,0x20);
}
ND::Ports::OutputB(0x20,0x20);
}

З цим ми вже повинні активувати IRQ, навіть якщо вони все ще нічого не роблять. У наступному розділі ми побачимо, як отримати дані з цих IRQ, таких як годинник або клавіатура.

NextDivel-IRQ


І цим закінчується сьогоднішня публікація. Як бачите зараз, я пишу менш регулярно через інші проблеми. Навіть так я продовжуватиму, поки не отримаю повнішу операційну систему


Залиште свій коментар

Ваша електронна адреса не буде опублікований. Обов'язкові для заповнення поля позначені *

*

*

  1. Відповідальний за дані: Мігель Анхель Гатон
  2. Призначення даних: Контроль спаму, управління коментарями.
  3. Легітимація: Ваша згода
  4. Передача даних: Дані не передаватимуться третім особам, за винятком юридичних зобов’язань.
  5. Зберігання даних: База даних, розміщена в мережі Occentus Networks (ЄС)
  6. Права: Ви можете будь-коли обмежити, відновити та видалити свою інформацію.

  1.   aitor_cz - сказав він

    Щиро дякую, Адріане, як тільки у мене буде трохи часу (зараз я досить зайнятий, серед іншого ще й операційною системою), я почну тестувати посібник поетапно.

  2.   рубін - сказав він

    Щиро дякую за мету.

  3.   Саске - сказав він

    Одне питання, я роблю проект на основі цих мов програмування
    * Html5
    * Css3
    * Java
    Моє питання полягає в тому, що я хотів би, щоб цей проект був виконуваним, щоб користувачі могли використовувати його в таких операційних системах, як Linux та Windows, не могли б ви сказати мені, як я це роблю

    1.    AdrianArroyoStreet - сказав він

      Це не має нічого спільного з цим, але я все одно відповідаю вам. Я припускаю, що це будуть HTML5, CSS3 та JavaScript, а не Java, оскільки HTML5 та Java уживаються фатально. За допомогою HTML5 ви можете створювати веб-сайти, як і раніше, до яких ви отримуєте доступ з Інтернету. Якщо ви хочете зробити його локальним, ви можете упакувати його як ОС Firefox та програму Chrome OS. Якщо ви хочете, щоб у кожній операційній системі був виконаний файл, погляньте на XUL Runner, який є інструментом для виконання XUL (і, отже, HTML5 всередині елемента) за допомогою механізму Gecko.

    2.    Соїд Перес - сказав він

      Фрейм або панель Java - дуже хороший варіант. Я створив кілька виконуваних програм у вікні, використовуючи класи Java-фреймів як веб-браузер, але замість того, щоб використовувати їх для будь-якої сторінки, я даю йому прямий шлях у коді, а за допомогою php я виконую речення Java через .jar, який опікується сталлю Хоча я б рекомендував використовувати HTML5, CSS3 та JavaScript, оскільки, як каже Адріан Java, для Html5 потрібен Fatal, і це принесло мені багато головних болів

  4.   люрбан - сказав він

    Було б непогано підручник про те, як створити власну мову програмування

  5.   Іван - сказав він

    Дуже добре в цій серії статей про те, як побудувати операційну систему, ви дізнаєтесь багато речей. Я з нетерпінням чекаю наступного запису, я вже хочу мати клавіатуру в ОС. Я возився з git-кодом, і не зміг змусити його працювати з портами 0x60 і 0x64. Незважаючи на те, що я думав, що для клавіатури було переривання, яке дало вам натиснуту клавішу.

    1.    AdrianArroyoStreet - сказав він

      Ви можете отримати введення з клавіатури без перерви, але ви повинні читати за допомогою ND :: Ports :: InputB на порту 0x60. Однак ідеальний спосіб зробити це за допомогою переривань IRQ. Наразі я намагаюся це зробити, і через це триває трохи більше часу.

      1.    карлосорта - сказав він

        Привіт, Адріане, я перевіряв код і вражений тим, що він робить, і наскільки це допомогло мені зрозуміти деякі речі.

        У мене є кілька невеликих питань про те, як це працює, і джерело - це те, що я отримав із вашого GIT:

        1. - У частині IRQ ви згадали, що позиції від 0 до 32 IDT використовувались для винятків та від 32 (0x20) до 45 (0x2D) для IRQ, але IRQ складають 16 , переназначення не було б від 0x20 до 0x30?

        2. - У частині IRQ зверніть увагу, що ви надіслали встановлені ворота до розділу IDT; Коли ви розділяєте їх, зверніть увагу, що воно більше не виробляє виняток ділення на 0, тому для кожної модифікації, яку потрібно внести, необхідно додавати IDT Flush (). Чому IDT змінюється при встановленні таймера, а розподіл між 0 перестає працювати?

        3. - Я намагався простежити код за допомогою печати, щоб взяти як вказівку на те, що він виконує (щоб не налагоджувати поетапно), і я зрозумів, що не працює IRQ, чи потрібно мені реєструвати щось інше до IRQ генеруються переривання?

        1.    карлосорта - сказав він

          Я забув згадати, що знайшов ці посилання з інформацією:
          http://arstechnica.com/civis/viewtopic.php?f=20&t=899001
          http://www.superfrink.net/athenaeum/OS-FAQ/os-faq-pics.html
          http://orga2.exp.dc.uba.ar/data/downloads/clasespracticas/interrupciones2_clase_17.pdf
          http://www.intel-assembler.it/PORTALE/4/231468_8259A_PIC.pdf

          Очевидно, для обробки IRQ необхідно враховувати, який тип обробника використовується, якщо PIC, APIC, IOAPIC. . . тощо. Чи є спосіб зробити динаміку управління IRQ або вам потрібно спробувати удачу?

  6.   карлосорта - сказав він

    Доброго дня Адріане.

    Я побачив, що у мене проблеми з IRQ, і тому код не можна вдосконалювати, я взяв копію проекту і почав його аналізувати; Я додав функцію до трафаретного друку для друку реєстрованих записів struct reg, під час переривання; Я знайшов кілька речей, серед них те, що платівка працює, і я досі не можу зрозуміти, чому; змінити переривання таймера на переривання клавіатури для тестування, і він робить те, що повинен, але я не можу знайти проблему, не могли б ви допомогти мені і продовжити цей хороший пост? 😀

    Я залишаю посилання (воно має деякі модифікації, оскільки я використовую Mageia і використовую Grub2, для перевірки використовую VirtualBox)
    https://www.mediafire.com/?93psrgaoozatse8

    Чекаючи вашої уважної відповіді, і якщо у вас є якісь запитання чи щось вам потрібно, я хотів би допомогти 🙂

    1.    карлосорта - сказав він

      Я забув згадати, що я також перевірив KernelPanic, тому що ISR не працювали, і у мене така сама проблема у верхній частині стека, значення фільтрується, і я не знаю, це мій компілятор чи проблема, я використовую GCC 4.8.2 з Mageia 4

    2.    AdrianArroyoStreet - сказав він

      Мені дуже подобається, що ти допомагаєш мені у проекті. Я справді застряг у таймері, і я не розумію, чому це не працює. Я провів тести, модифікуючи досить багато речей, і це не вийшло. В даний час я не можу редагувати код (я перебуваю у відпустці), але якнайшвидше подивлюсь його. Я даю вам посилання з інформацією про цю проблему, яка, здається, є чимось загальним: http://wiki.osdev.org/I_Cant_Get_Interrupts_Working

      Що стосується винятків, я думаю, я пам'ятаю, що вам потрібно зателефонувати на "sti" в ASM, щоб активувати їх, хоча очевидно, що десь щось не так.

      1.    карлосорта - сказав він

        Дякую за вашу відповідь і так, справді. Переривання були невдалими, але це була проблема з вставкою кодів у стек і проблема з кастингом, я перевірю посилання і буду робити тести. Якщо я вирішу це питання, я повідомлю вас, а якщо ні, то повідомим вас про прогрес. Зі святом 🙂

      2.    карлосорта - сказав він

        Неможливо побачити зібраний код? Щось дивне відбувається, і я не можу знайти що? Подивіться на цей екран (я розмістив посилання в кінці), це щось дивне, оскільки у функції IRQ 2 (клавіатура) він входить Складіть значення 0 і 0x20 (32, тому пристосуйте його для тестування), потім пушаль (32-розрядні регістри GPR), потім регістри сегментації, а потім верх стека, а потім зателефонуйте IRQ Handler. Я почав бачити кожен стек, і, мабуть, він у порядку, але якщо ви можете побачити вихідні дані віртуальної машини, ви можете побачити, що вона стекує ще один елемент, я не можу знайти де, я просто знаю, що це 0x10, і структура виходить з ладу. Це структура записів.

        struct regs {
        uint32_t gs, fs, es, ds; / * останнє натискання секунд * /
        uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; / * штовхається "пушаль" * /
        uint32_t int_no, код помилки; /* Код помилки */
        uint32_t eip, cs, eflags, useresp, ss; / * Складається на перерву * /
        };

        Це дає мені балончик, який поміщає ще один елемент у верхню частину, і я не можу знайти, де він укладений, якщо, мабуть, все складено як слід. Ви уявляєте, що це може бути?

        http://www.subeimagenes.com/img/sin-titulo-1036729.jpg

  7.   карлосорта - сказав він

    Примусьте переривання клавіатури працювати, але не переривання таймера; помилка полягала в тому, як вона компілюється, я використовував objdump, щоб побачити кінцевий об'єкт, і виявилося, що кожна функція, яка була введена навіть з використанням "asm volatile", також супроводжувалася pushl ebp, mov ebp, esp. Потім просто додайте до нього ebp popl, щоб відновити початковий стек, і він безперешкодно передасть аргументи. Тут я додаю код для тих, хто хоче його перевірити, і якщо ви можете дізнатися, чому переривання не генерується таймером, я хотів би його знати, і я додаю посилання, де вони говорять про багатозадачність http://www.jamesmolloy.co.uk/tutorial_html/9.-Multitasking.html
    Наступний Divel
    https://www.mediafire.com/?kmo83dxyzc7c3cz

    1.    AdrianArroyoStreet - сказав він

      Зрозумів. Це була помилка в іншому місці, яка вплинула на активацію таймера PIC, зокрема в переназначенні IRQ було два рядки, які мені довелося змінити. Завдяки тому, що я міг побачити на веб-сайті код, який на той момент мав щось інше, і натиснути! Зміни відбувались у напрямку:
      ND :: Порти :: OutputB (PIC1 + 1, 0xFF);
      ND :: Порти :: OutputB (PIC2 + 1, 0xFF);

      Вам довелося змінити значення з 0xFF (я б сказав, що це вказує на вимкнене) на 0x00 (я б сказав, що це вказує на увімкнене), хоча я насправді не впевнений, але воно працює. Я оновив код на GitHub. Щиро дякую за допомогу в проекті, від якого я трохи відмовився через цю проблему. H

      1.    карлосорта - сказав він

        Ласкаво просимо, я з нетерпінням чекаю наступного оновлення теми, і ви можете розраховувати на мене що завгодно 🙂 (Y)

      2.    карлосорта - сказав він

        Змінити процедуру захоплення рядків клавіатури; тому що це читання, коли ключ відпущений, і він встановлює 0 в буфер, що створює проблеми з читанням, і в кінці "\ n" змініть його на ", щоб працював правильний друк

  8.   Соїд Перес - сказав він

    Привіт, я прочитав весь ваш допис, хоча на практиці це не більше 2 дописів, це дійсно дуже добре, збережіть все, але мені дійсно потрібно буде вивчити c ++ та posix, щоб зрозуміти це, тому що я знаю про "c" (Я захоплений цією мовою програмування), але хоча c ++ - це c OO, я ніколи над цим не працював, прочитайте мені кілька підручників у google, а потім я поверну це дуже цікаве, і запитання - це запуск вікна схожий на Linux?

    1.    AdrianArroyoStreet - сказав він

      Завантаження в Windows схоже в тому сенсі, що це спосіб завантаження системи з процесором x86 і операційна система, побудована на ньому, не має великого впливу. Ми все одно насправді не завантажуємось, це починає GRUB для нас. GRUB, призначений для завантаження Linux, може завантажувати Windows і в цьому випадку NextDivel.

      1.    соїд - сказав він

        добре, дякую, це означає, що те, що я хочу зробити, можливо, я вже вивчаю c ++, і я створив деякі програми та встановив вашу систему на pendrive, і я вивчаю це більш докладно - дуже хороший пост