Emulera Linus Torvalds: Skapa ditt eget operativsystem från grunden (VI)

Tja, efter en liten parentes fortsätter vi med vår serie handledning. Om vi ​​går tillbaka till föregående kod måste vi ha ISR för divisionen med noll. Nu måste vi fylla i resten av ISR: erna som vi hade publicerat (de första 32). Nåväl kommer vi att fortsätta programmera avbrott, vi kommer att göra IRQ: erna också kända som Avbryter begäranden. Dessa IRQ: er genereras av hårdvaruenheter som tangentbord, möss, skrivare etc. Ursprungligen mappas de första 8 IRQ: erna automatiskt till IDT-positionerna 8 till 15. Eftersom vi har använt de första 32 för undantag måste vi mappa dem om. Vi kommer att sätta IRQ från 32 till 45. För detta måste vi först kartlägga IRQ: erna:

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

Nu skapar vi en funktion för att installera IRQ: erna:

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

Domen i asm sti vi aktiverar IRQ: erna. Tja, nu går vi med något som liknar ISR. Funktionerna för en grundläggande IRQ:

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

En vanlig del (samma som 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"
);
}

Och en grundläggande hanterare:

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

Med detta borde vi redan ha IRQ aktiverad även om de fortfarande inte gör någonting. I nästa kapitel kommer vi att se hur man hämtar data från dessa IRQ, t.ex. klockan eller tangentbordet.

NextDivel-IRQ


Och med detta slutar dagens inlägg. Som ni ser nu skriver jag mindre regelbundet på grund av andra problem. Ändå fortsätter jag tills jag har ett mer komplett operativsystem


22 kommentarer, lämna din

Lämna din kommentar

Din e-postadress kommer inte att publiceras. Obligatoriska fält är markerade med *

*

*

  1. Ansvarig för uppgifterna: Miguel Ángel Gatón
  2. Syftet med uppgifterna: Kontrollera skräppost, kommentarhantering.
  3. Legitimering: Ditt samtycke
  4. Kommunikation av uppgifterna: Uppgifterna kommer inte att kommuniceras till tredje part förutom enligt laglig skyldighet.
  5. Datalagring: databas värd för Occentus Networks (EU)
  6. Rättigheter: När som helst kan du begränsa, återställa och radera din information.

  1.   aitor_cz sade

    Tack så mycket Adrian, så fort jag har lite tid (nu är jag ganska upptagen, bland annat också med ett operativsystem) kommer jag att börja testa handledningen steg för steg.

  2.   Rubin sade

    Tack så mycket för tute.

  3.   Sasuke sade

    En fråga jag gör ett projekt baserat på dessa programmeringsspråk
    * Html5
    * Css3
    * Java
    Min fråga är att jag skulle vilja att det här projektet skulle kunna köras, så att användarna använder det i operativsystem som linux och windows, kan du berätta för mig hur jag gör det

    1.    AdrianArroyoStreet sade

      Det har inget att göra med detta men jag svarar dig ändå. Jag antar att det kommer att vara HTML5, CSS3 och JavaScript inte Java, eftersom HTML5 och Java går dåligt. Med HTML5 kan du skapa webbplatser som tidigare som nås från internet. Om du vill göra det lokalt kan du paketera det som en Firefox OS- och Chrome OS-app. Om det du vill är att i varje operativsystem finns en körbar titt på XUL Runner som är ett verktyg för att köra XUL (och därmed HTML5 inuti elementet) med Gecko-motorn.

    2.    Soid perez sade

      Java-ram eller panel är ett mycket bra alternativ Jag har skapat några körbara appar i fönstret med java-ramklasserna som en webbläsare men istället för att använda den för vilken sida som helst ger jag den en direkt sökväg i koden och med php kör jag java-meningar genom en .jar som tar hand om stål. Även om jag skulle rekommendera att använda HTML5, CSS3 och JavaScript eftersom som Adrian Java säger är det dödligt med Html5 och det gav mig många huvudvärk

  4.   urban sade

    En handledning om hur du skapar ditt eget programmeringsspråk skulle vara trevligt

  5.   Ivan sade

    Mycket bra denna serie artiklar om hur man bygger ett operativsystem, du lär dig många saker. Jag ser fram emot nästa post, jag vill redan ha ett tangentbord i operativsystemet. Jag har trasslat med git-koden och jag har inte lyckats få den att fungera med port 0x60 och 0x64. Även om jag trodde att för tangentbordet fanns ett avbrott som gav dig den tryckta knappen.

    1.    AdrianArroyoStreet sade

      Du kan faktiskt få tangentbordets ingång utan avbrott, men du måste läsa med ND :: Ports :: InputB på port 0x60. Men det perfekta sättet att göra detta är med IRQ-avbrott. Jag försöker för närvarande göra det och det tar lite längre tid att fortsätta på grund av det.

      1.    carlosorta sade

        Hej Adrian, jag har kollat ​​koden och jag är imponerad av vad den gör och hur bra det har hjälpt mig att förstå vissa saker.

        Jag har några små frågor om hur det fungerar och källan är den jag fick från din GIT:

        1.- I delen av IRQ: erna nämnde du att positionerna från 0 till 32 av IDT användes för undantag och från 32 (0x20) till 45 (0x2D) för IRQ: erna, men IRQ: erna är totalt 16, skulle ombildningen inte vara från 0x20 till 0x30?

        2. - I IRQ-delen, notera att setgatesna skickades till IDT-sektionen; När du separerar dem, lägg märke till att det inte längre ger undantag för division med 0, så det är nödvändigt att lägga till IDT Flush () för varje modifiering som görs. Varför ändras IDT när timern ställs in och uppdelningen mellan 0 slutar fungera?

        3.- Jag försökte spåra koden med lite utskrift för att ta som en indikation på vad den kör (för att inte felsöka steg för steg) och jag insåg att ingen IRQ är i drift, måste jag registrera något annat till IRQ-avbrott genererade?

        1.    carlosorta sade

          Jag glömde att nämna att jag hittade dessa länkar med information:
          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

          Tydligen för hantering av IRQ är det nödvändigt att ta hänsyn till vilken typ av hanterare som används om, PIC, APIC, IOAPIC. . .etc. Finns det ett sätt att skapa en dynamik inom IRQ-hantering eller behöver du prova tur?

  6.   carlosorta sade

    God eftermiddag Adrian.

    Jag såg att jag hade problem med IRQ: erna och det var därför koden inte kunde avanceras, jag tog en kopia av projektet och började analysera den; Jag lade till en funktion i screentrycket för att skriva ut regposterna för struct reg, när jag gjorde avbrotten; Jag hittade flera saker, bland annat att ett register körs och jag kan fortfarande inte hitta varför; ändra timeravbrottet för tangentbordsavbrottet för att testa och göra vad det borde men jag kan inte hitta problemet, kan du hjälpa mig och fortsätta med det här bra inlägget? 😀

    Jag lämnar länken (den har några ändringar eftersom jag använder Mageia och jag använder Grub2, jag använder VirtualBox för att testa det)
    https://www.mediafire.com/?93psrgaoozatse8

    Väntar på ditt uppmärksamma svar och om du har några frågor eller behöver något vill jag hjälpa till 🙂

    1.    carlosorta sade

      Jag glömde att nämna att jag också kollade KernelPanic eftersom ISR: n inte fungerade och jag har samma problem högst upp i stacken ett värde filtreras och jag vet inte om det är min kompilator eller om det finns ett problem, jag använd GCC 4.8.2 med Mageia 4

    2.    AdrianArroyoStreet sade

      Jag gillar verkligen att du hjälper mig i projektet. Jag fastnade verkligen i timern och jag förstår inte varför det inte fungerar. Jag gjorde test för att modifiera en hel del saker och det gick inte. För närvarande kan jag inte redigera koden (jag är på semester borta) men jag kommer att ta en titt på den så snart jag kan. Jag ger dig en länk med information om detta problem som verkar vara något vanligt: http://wiki.osdev.org/I_Cant_Get_Interrupts_Working

      När det gäller undantagen tror jag att jag kommer ihåg att du måste ringa "sti" i ASM för att aktivera dem även om det är tydligt att något är fel någonstans.

      1.    carlosorta sade

        Tack för ditt svar och ja. Avbrotten misslyckades men det var ett problem att infoga koder i stacken och ett castingproblem, jag kommer att kontrollera länken och jag kommer att göra tester. Om jag löser det kommer jag att meddela dig och om inte kommer jag att informera dig om framsteg. God helgdag Hol

      2.    carlosorta sade

        Det kommer inget sätt att se den samlade koden? Händer något konstigt och jag kan inte hitta vad? Titta på den här skärmen (jag lägger länken i slutet), det är något konstigt eftersom i IRQ 2-funktionen (tangentbordet ) kommer det in i stacken värdet 0 och 0x20 (32, så passa det för att testa) sedan pushal (32-bitars GPR-registren) följt av segmenteringsregistren och sedan toppen av stacken och ring sedan IRQ Handler. Jag började se varje stack och tydligen är det i ordning men om du kan se utdata från den virtuella datorn kan du se att den staplar ytterligare ett element, jag kan inte hitta var, jag vet bara att det är en 0x10 och strukturen blir ur funktion. Detta är rekordstrukturen.

        struct regs {
        uint32_t gs, fs, es, ds; / * tryckte sekunderna sist * /
        uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; / * tryckt av 'pushal' * /
        uint32_t int_no, err_code; /* Felkod */
        uint32_t eip, cs, eflags, useresp, ss; / * Staplade vid paus * /
        };

        Det stör mig att det sätter ett element till överst och jag kan inte hitta var det är staplat om allt tydligen är staplat som det borde vara. Har du någon aning om vad det kan vara?

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

  7.   carlosorta sade

    Få tangentbordsavbrottet att fungera men inte timern avbryt; felet var i hur det kompilerades, jag använde objdump för att se det slutliga objektet och det visade sig att varje funktion som ingick även med "asm flyktig" åtföljdes också av en pushl ebp, mov ebp, esp. Lägg bara till en popl ebp i den för att återställa den ursprungliga stacken och den kommer att skicka argumenten utan att misslyckas. Här bifogar jag koden för dem som vill kontrollera den och om du kan ta reda på varför avbrottet inte genereras av timern, skulle jag gärna veta det och jag bifogar en länk där de pratar om multitasking http://www.jamesmolloy.co.uk/tutorial_html/9.-Multitasking.html
    Nästa Divel
    https://www.mediafire.com/?kmo83dxyzc7c3cz

    1.    AdrianArroyoStreet sade

      Jag förstår. Det var ett fel på ett annat ställe som påverkade aktiveringen av Timer PIC, särskilt i IRQ-ombildningen fanns det två rader som jag var tvungen att ändra. Tack vare det faktum att jag kunde se en kod på en webbplats som då hade något annat och klicka! Förändringen var i linje med:
      ND :: Portar :: OutputB (PIC1 + 1, 0xFF);
      ND :: Portar :: OutputB (PIC2 + 1, 0xFF);

      Du var tvungen att ändra värdet på 0xFF (jag skulle säga att det indikerar inaktiverat) till 0x00 (jag skulle säga att det indikerar aktiverat) även om jag inte är riktigt säker, men det fungerar. Jag har uppdaterat koden på GitHub. Tack så mycket, mycket för att du hjälpte mig med projektet som jag hade övergivit lite på grund av detta problem. H

      1.    carlosorta sade

        Du är välkommen, jag ser fram emot nästa uppdatering av ämnet och du kan lita på mig för vad som helst 🙂 (Y)

      2.    carlosorta sade

        Ändra rutin för att fånga tangentbordsträngar; eftersom den läser när nyckeln släpps och den monterar ett 0 i bufferten, vilket ger problem i läsningen och i slutet ändras '\ n' till »så att rätt utskrift fungerar

  8.   Soid perez sade

    Hej, jag läste hela inlägget, även om det i praktiken inte är mer än två inlägg, det är verkligen väldigt bra, spara allt, men jag måste verkligen studera c ++ och posix för att förstå det för jag vet om "c" (Jag är fascinerad av det programmeringsspråket) men även om c ++ är c ​​OO har jag aldrig riktigt jobbat med det, läs några handledningar för mig på Google och sedan returnerar jag det här väldigt intressant och en fråga, liknar fönstrets start Linux?

    1.    AdrianArroyoStreet sade

      Att starta i Windows är liknande i den meningen att det här är sättet att starta ett system med en x86-processor och operativsystemet som bygger på det har liten påverkan. Vi startar egentligen inte på något sätt, det börjar GRUB för oss. GRUB, designad för att starta Linux, kan starta Windows och i det här fallet NextDivel.

      1.    fast sade

        ok tack det betyder att det jag vill göra är möjligt jag studerar redan c ++ och skapar några appar och installerar ditt system på en pendrive och jag studerar det mer detaljerat är ett mycket bra inlägg