2016-09-23 2 views
2

Hilfe, ich laufe das OS und es stürzt ab! IDT Loadet normalerweise. Was ich falsch gemacht habe, ist wirklich schwer! Ich muss os im geschützten Modus schreiben!Assembler + C oder ich kann keine Interrupts erhalten

#define IT 0x000000 
    #define IR 0x000800 
    #define SCS 0x8 
    #define IRQ_HANDLER(func) void func (void)\ 
    {asm(#func ": pusha \n call _" #func " \n movb $0x20, %al \n outb %al, $0x20 \n popa \n iret \n");}\ 
    void _ ## func(void) 
     void init_interrupts() { 
      int i=0; 
      unsigned short *ir=IR; 
      for(i=0;i<256*8;i++){ 
       *(ir+i)=0; 
      } 
      *(ir)=256*8-1; 
      *(ir+2)=(IT &0xFFFF0000)>>16; 
      *(ir+4)=(IT&0x0000FFFF); 
      set_int_handler(0x20, timer_int_handler, 0x8E); 
      //set_int_handler(0x21, print_c, 0x8E); 
      asm("lidt 0(,%0,)"::"a"(IR)); 
      opb(0x21,0xfd); 
      opb(0xa1,0xff); 
      opb(0x20,0x20); opb(0xa0,0x20); 
      asm("sti"); 
     } 

     void set_int_handler(char index, void *handler, char type) { 
     asm("pushf \n cli"); 
     char *ad=IT; 
     *(ad+index*8)=(char)(handler)&0x000000FF; 
     *(ad+index*8+1)=((char)(handler)&0x0000FF00)>>8; 
     *(ad+index*8+2)=0x8; 
     *(ad+index*8+3)=0; 
     *(ad+index*8+4)=0; 
     *(ad+index*8+5)=type; 
     *(ad+index*8+6)=((char)(handler)&0x00FF0000)>>16; 
     *(ad+index*8+7)=((char)(handler)&0xFF000000)>>24; 
     asm("popf"); 
    } 
    ... 


Ich weiß nicht, was zu tun ist!

+2

Sie können Inline Assembly nicht so verwenden. Der Compiler verspricht nicht, den Stack in dem Zustand zu belassen, in dem er sich nach dem 'pushf \ n cli' befindet, wenn er den' popf' ausführt. –

+2

Oben auf die Antwort und Kommentare bereits. Ich sehe, dass du 'opb (0x21,0xfd); opb (0xa1,0xff); 'was andeutet, dass Sie alle 16 Interrupts maskiert haben ** außer ** IRQ1, was der Tastatur-Interrupt ist, aber dann setzen Sie den Interrupt-Handler für den Timer, der IRQ0 ist. Wolltest du das machen? 0xfd = binär 11111101 was ist das, was Sie den Master-PIC, der IRQ1 wäre. Vielleicht meintest du 0xfe? –

Antwort

3

Erstens, auf die eine oder andere Weise erlauben die meisten Compiler Ihnen create an ISR directly.

Zweitens sollten Sie alles von Anfang an abfangen, es sei denn, Sie möchten, dass das System beim ersten unbehandelten oder falschen Interrupt abstürzt (was auf den ersten Blick so aussieht, als würde es weitergehen).

Ein richtiges Interrupt-Handling-Subsystem würde den Code viel sauberer und portabler machen, so dass Sie IRQs für dumme Busse (wie ISA) testen und gemeinsam genutzte IRQs sauber weiterleiten können.

Die meisten Emulatoren unterstützen das GDB-Protokoll und ermöglichen das problemlose Debuggen dieser Art von Fehlern. Zum Beispiel können Sie QEMU mit -d int und -no-reboot starten, um diese Art von Problemen zu debuggen. Sobald ein Fehler auftritt, können Sie ihn vom Debugger aus untersuchen. Sie können einige Anweisungen finden, um in QEMU Wikibook zu beginnen. Sie können auch BOCHS ausprobieren, es kommt mit einem internen Debugger, der besser bei Low-Level-Kram ist und die Emulation ist manchmal genauer.

+0

Die meisten 32-Bit-x86-Compiler lassen Sie keine ISR direkt erstellen, da die Interruptbehandlung im geschützten Modus im Allgemeinen zu kompliziert ist, um von einem allgemeinen Prolog und Epilog der Interruptfunktion behandelt zu werden. –

+0

GCC und Clang tun, ebenso wie Borland und Watcom IIRC (seit vielen Jahren ...). –

+0

Hmm ... GCC war es nicht gewohnt, es sieht so aus, als hätten sie es erst vor einem Jahr hinzugefügt. Der 32-Bit-C-Compiler von Borland unterstützt dies nicht. Sieht nach Watcom aus. In jedem Fall ist es in einem Betriebssystem nicht sehr nützlich, weil Sie nicht auf die gespeicherten Register zugreifen können und Sie den Inhalt bei der Interrupt-Rückgabe nicht wechseln können. –