Эмуляция Линуса Торвальдса: создайте собственную операционную систему с нуля (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 STI мы активируем 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, таких как часы или клавиатура.

СледующийDivel-IRQ


И на этом заканчивается сегодняшний пост. Как видите, сейчас я пишу реже из-за других проблем. Тем не менее, я буду продолжать, пока не получу более полную операционную систему.


22 комментариев, оставьте свой

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

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

*

*

  1. Ответственный за данные: Мигель Анхель Гатон
  2. Назначение данных: контроль спама, управление комментариями.
  3. Легитимация: ваше согласие
  4. Передача данных: данные не будут переданы третьим лицам, кроме как по закону.
  5. Хранение данных: база данных, размещенная в Occentus Networks (ЕС)
  6. Права: в любое время вы можете ограничить, восстановить и удалить свою информацию.

  1.   aitor_cz сказал

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

  2.   Ruby сказал

    Большое спасибо за туту.

  3.   Саске сказал

    Один вопрос Я делаю проект на основе этих языков программирования
    * Html5
    * Css3
    *Ява
    Мой вопрос: я бы хотел, чтобы этот проект был исполняемым, чтобы пользователи использовали его в операционных системах, таких как Linux и Windows, не могли бы вы рассказать мне, как я это делаю?

    1.    АдрианАрройоУлица сказал

      Это не имеет отношения к этому, но я все равно вам отвечу. Я предполагаю, что это будут HTML5, CSS3 и JavaScript, а не Java, поскольку HTML5 и Java фатально уживаются. С HTML5 вы, как и раньше, можете создавать веб-сайты, доступные из Интернета. Если вы хотите сделать его локальным, вы можете упаковать его как приложение Firefox OS и Chrome OS. Если вы хотите, чтобы в каждой операционной системе был исполняемый файл, взгляните на XUL Runner, который является инструментом для выполнения XUL (и, следовательно, HTML5 внутри элемента) с движком Gecko.

    2.    Соид Перес сказал

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

  4.   Lurban сказал

    Было бы неплохо узнать, как создать свой собственный язык программирования.

  5.   Иван сказал

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

    1.    АдрианАрройоУлица сказал

      Фактически вы можете получать ввод с клавиатуры без прерывания, но вы должны читать с помощью 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 и поэтому код не может быть расширен, я взял копию проекта и начал анализировать; Я добавил функцию трафаретной печати для печати записей reg структуры reg в момент прерывания; Я обнаружил несколько вещей, в том числе то, что реестр работает, и я до сих пор не могу понять, почему; измените прерывание таймера для прерывания клавиатуры, чтобы проверить и сделать то, что должно, но я не могу найти проблему, не могли бы вы мне помочь и продолжить этот хороший пост? 😀

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

    Жду вашего внимательного ответа, и если у вас есть вопросы или вам что-то нужно, я бы хотел помочь 🙂

    1.    Карлосорта сказал

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

    2.    АдрианАрройоУлица сказал

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

      Что касается исключений, думаю, я помню, что вам нужно позвонить в "sti" в ASM, чтобы активировать их, хотя ясно, что где-то что-то не так.

      1.    Карлосорта сказал

        Спасибо за ответ и да, конечно. Прерывания не работали, но возникла проблема с вставкой кодов в стек и проблема с кастингом, я проверю ссылку и буду проводить тесты. Если я решу ее, я дам вам знать, а если нет, я сообщу вам о прогрессе. С праздником 🙂

      2.    Карлосорта сказал

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

        struct regs {
        uint32_t gs, fs, es, ds; / * нажал последние секунды * /
        uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; / * толкается 'pushal' * /
        uint32_t int_no, err_code; /* Код ошибки */
        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. Затем просто добавьте к нему popl ebp, чтобы восстановить исходный стек, и он обязательно передаст аргументы. Здесь я прикрепляю код для тех, кто хочет его проверить, и если вы можете узнать, почему прерывание не генерируется таймером, я хотел бы узнать это, и я прикрепляю ссылку, где они говорят о многозадачности http://www.jamesmolloy.co.uk/tutorial_html/9.-Multitasking.html
    Следующее погружение
    https://www.mediafire.com/?kmo83dxyzc7c3cz

    1.    АдрианАрройоУлица сказал

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

      Вам пришлось изменить значение с 0xFF (я бы сказал, что он отключен) на 0x00 (я бы сказал, что это означает, что он включен), хотя я не совсем уверен, но это работает. Я обновил код на GitHub. Большое спасибо за помощь в проекте, от которого я немного отказался из-за этой проблемы. ЧАС

      1.    Карлосорта сказал

        Пожалуйста, я с нетерпением жду следующего обновления темы, и вы можете рассчитывать на меня во всем 🙂 (Y)

      2.    Карлосорта сказал

        Измените процедуру захвата строки клавиатуры; потому что он читает в момент отпускания клавиши и устанавливает 0 в буфер, что вызывает проблемы при чтении, и в конце '\ n' измените его на », чтобы корректная печать работала.

  8.   Соид Перес сказал

    Здравствуйте, я прочитал весь ваш пост, хотя на практике это не более двух постов, это действительно очень хорошо, сохраните все, но мне действительно нужно будет изучить c ++ и posix, чтобы понять это, потому что я знаю о "c" (Я очарован этим языком программирования), но хотя c ++ - это c OO, я никогда не работал над ним, прочтите мне несколько руководств в Google, а затем я возвращаю это очень интересное и вопрос, похож ли запуск окна на linux?

    1.    АдрианАрройоУлица сказал

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

      1.    Soid сказал

        хорошо, спасибо, это означает, что то, что я хочу сделать, возможно, я уже изучаю c ++, и я создал несколько приложений и установил вашу систему на флешку, и я изучаю ее более подробно, это очень хороший пост