Емулиране на Linus Torvalds: Създайте своя собствена операционна система от нулата (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 активираме IRQs. Е, сега отиваме с нещо подобно на 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 OS и Chrome OS. Ако това, което искате, е, че във всяка операционна система има изпълним файл, погледнете XUL Runner, който е инструмент за изпълнение на XUL (и следователно HTML5 вътре в елемента) с механизма Gecko.

    2.    Soid perez каза той

      Java рамката или панелът са много добра опция Създадох някои изпълними приложения в прозореца, използвайки класовете на java frame като уеб браузър, но вместо да ги използвам за която и да е страница, аз му давам директен път в кода и с php изпълнявам java изречения чрез .jar, който се грижи за стоманата. Въпреки че бих препоръчал да се използват HTML5, CSS3 и JavaScript, тъй като както казва Адриан Java, е необходимо Fatal с Html5 и ми донесе много главоболия

  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; / * избутано от 'pushal' * /
        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 :: Портове :: ИзходB (PIC1 + 1, 0xFF);
      ND :: Портове :: ИзходB (PIC2 + 1, 0xFF);

      Трябваше да промените стойността на 0xFF (бих казал, че означава деактивиран) на 0x00 (бих казал, че означава активиран), въпреки че не съм наистина сигурен, но работи. Актуализирах кода на GitHub. Благодаря ви много, много, че ми помогнахте с проекта, който бях малко изоставен поради този проблем. З.

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

        Добре дошли, ще се радвам на следващата актуализация на темата и можете да разчитате на мен за всичко 🙂 (Y)

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

        Променете рутинната процедура за улавяне на низовете на клавиатурата; тъй като се чете, когато ключът се освободи и той монтира 0 в буфера, което създава проблеми при четенето и в края на \ \ 'го променя на

  8.   Soid perez каза той

    Здравейте, прочетох целия ви пост, въпреки че на практика това е не повече от 2 публикации, наистина е много добре, запазете всичко, но наистина ще трябва да изуча c ++ и posix, за да го разбера, защото знам за "c" (Очарована съм от този език за програмиране), но въпреки че c ++ е c OO, никога не съм работил по него, прочетете ми няколко урока в google и след това връщам това много интересно и въпрос, стартирането на прозореца подобно ли е на linux?

    1.    AdrianArroyoStreet каза той

      Стартирането в Windows е подобно в смисъл, че това е начинът за зареждане на система с процесор x86 и изградената върху нея операционна система има малко влияние. Ние така или иначе не се зареждаме, той стартира GRUB за нас. GRUB, предназначен за зареждане на Linux, може да стартира Windows и в този случай NextDivel.

      1.    соид каза той

        добре, благодаря, това означава, че това, което искам да направя, е възможно, аз вече изучавам c ++ и създавам някои приложения и инсталирам вашата система на pendrive и го изучавам по-подробно е много добър пост