Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: Pk3 am 22. August 2009, 10:56

Titel: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 10:56
Hi, hab mal wieder ein Problem :roll:, ich kann in meinem C Kernel (PM)
keine Interrupts ausführen. Wenn ich z.B. int 16h ausführe,
bleibt mein Kernel stehen, passiert nichts mehr.

Hier mal der Code.

char IDT[256 * 8];
void LoadIDT();

void begin() {
LoadIDT();
asm("sti\n\tint $0x16");
v_print("Test");
}

void LoadIDT() {
struct {
unsigned int limit;
unsigned int base;
}  __attribute__((packed)) idt_ptr = {
.limit  = 256*8 - 1,
.base  = (unsigned int)IDT,

};

asm("lidt %0" : : "m" (idt_ptr));
}

Weiß jemand warum das nicht geht?

Edit:
Bochs meldet dazu:

00004421957-i-@000013f9-[CPU0 ] >> int 0x16 : CD16
00004421957-e-@000013f9-[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Titel: Re: IDT funktioniert nicht
Beitrag von: kevin am 22. August 2009, 11:24
Wird die IDT auch irgendwo mit sinnvollen Werten gefüllt?
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 11:27
Also das ist der gesamte Code den ich gepostet habe.
Wie und mit welchen Werten fülle ich sie?
Titel: Re: IDT funktioniert nicht
Beitrag von: rizor am 22. August 2009, 12:06
Du musst zu jedem Interrupt, auf den du reagieren möchtest, das Gate definieren.
Das kannst du dir im Wiki anschauen.
Da steht genau drin was du in die Einträge schreiben kannst.
Du musst halt definieren, wer den Interrupt auslösen darf und was für eine Art von Interrupt-Gate das ist.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 12:15
http://lowlevel.brainsware.org/wiki/index.php/IDT

Da steht aber nicht, wie man eine IDT füllt, sondern nur die Werte.
Kannst du mir vielleicht bitte ein Beispiel geben  :-)?
Titel: Re: IDT funktioniert nicht
Beitrag von: rizor am 22. August 2009, 12:36
Es gibt bestimmte Flags, dir du an einem Gate setzen kannst:

#define IDT_TASK_GATE 0x5
#define IDT_INT_GATE_16 0x6
#define IDT_TRAP_GATE_16 0x7
#define IDT_INT_GATE_32 0xe
#define IDT_TRAP_GATE_32 0xf
#define IDT_SYS_SEGMENT 0x10
#define IDT_RING_0 0x0
#define IDT_RING_1 0x20
#define IDT_RING_2 0x40
#define IDT_RING_3 0x60
#define IDT_PRESENT 0x80

#define IDT_STD_GATE IDT_PRESENT | IDT_RING_0 | IDT_INT_GATE_32
#define IDT_SYSCALL_GATE IDT_PRESENT | IDT_RING_3 | IDT_INT_GATE_32

Das sind bestimme Flags.
STD_GATE beschreibt bei mir einfach die normalen Interrupts.
Die sollten am besten nicht aus dem Userspace ausgelöst werden können.
Die Syscalls hingegen schon.

Du kannst dir die ganzen Gates definieren wie du willst.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 12:43
Ich hab das jetzt so verstanden:

void LoadIDT() {
unsigned int i=0;
while(i < 256) {
IDT[i] = IDT_STD_GATE;
i++;
}

struct {
unsigned int limit;
unsigned int base;
}  __attribute__((packed)) idt_ptr = {
.limit  = 256*8 - 1,
.base  = (unsigned int)IDT,

};

asm("lidt %0" : : "m" (idt_ptr));
}

Ist das so richtig?
Titel: Re: IDT funktioniert nicht
Beitrag von: rizor am 22. August 2009, 12:51
Das kannst du so machen.
Allerdings brauchst du nicht jedes gate definieren.
Es ist effektiver und sicher wenn du nicht jeden Eintrag definierst.
Am besten ist es, wenn du nur die Gates definierst, die du auch wirklich brauchst.
Den Rest kannst du mit NULL auffüllen.

So könnte eine Methode aussehen:
void idt_set_gate(uint16_t num , uint32_t base , uint16_t sel , uint8_t attr){
if(num < IDT_SIZE){
if(IDT[num].offset_low != NULL)
panic("Tried to write into a set IDT-Entry" , NO_CPU_STATE);

IDT[num].offset_low = (base & 0xFFFF);
IDT[num].offset_high = (base >> 16) & 0xFFFF;
IDT[num].selector = sel;
IDT[num].zero = 0;
IDT[num].attribute = attr;
}
else
panic("Tried to set a wrong interrupt-gate" , NO_CPU_STATE);
}

Bei mir sehen die Gates wie folgt aus:
typedef struct{
uint16_t offset_low;
uint16_t selector;
uint8_t zero;
uint8_t attribute;
uint16_t offset_high;
}id_table;

Der Call sieht dann für die Division by zero Exception so aus:
idt_set_gate(0, (unsigned)intr_0, 0x08, IDT_STD_GATE);
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 12:56
Ah ok, also so geht es auch?

Weil sobald ich das hier mache, funktioniert wieder nix mehr:

asm("sti\n\ttaste:\n\tmov $0x1, %ah\n\tint $0x16\n\tjz taste\n\tmov 0x0, %ah\n\tint $0x16");
Bochs sagt wieder:

00004424009-i-@0000141d-[CPU0 ] >> int 0x16 : CD16
00004424009-e-@0000141d-[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting

 :-(

Edit

Dein Code geht bei mir nicht, kommen unmengen an Fehlern beim
komplimieren, liegt vielleicht daran das du einen anderen Compiler
als ich verwendest.
Titel: Re: IDT funktioniert nicht
Beitrag von: kevin am 22. August 2009, 13:04
void LoadIDT() {
unsigned int i=0;
while(i < 256) {
IDT[i] = IDT_STD_GATE;
i++;
}
Das ist Blödsinn. Die entscheidende Information lässt du weg, nämlich was passieren soll, wenn der Interrupt aufgerufen werden soll. Es sei denn, du hast abweichend von rizor deinen Interrupthandler noch in IDT_STD_GATE reinkodiert.
Titel: Re: IDT funktioniert nicht
Beitrag von: rizor am 22. August 2009, 13:05
Machst du das noch nach deiner Methode?

Sorry, mir ist eben aufgefallen, dass du die Gates falsch initialisierst.
Du musst dir so einen Struct aufbauen, da die Gates nicht nur char* sind.
Das STD_GATE ist an sich nur das Attribut des Gates.
Du musst natürlich auch noch eine Methode angeben, die bei dem Gate angesrungen werden soll.
Ich habe mir dafür einfach für jedes Interrupt eine Asm-Methode geschrieben, die dann die Interrupt-Nummer speichert.

Wenn ein Interrupt ausgelöst wird, schaut die CPU in der IDT nach und sucht nach dem passenden Gate.
Wenn dieses gefunden wurde,springt die CPU die dort eingetragene Methode an.
Titel: Re: IDT funktioniert nicht
Beitrag von: kevin am 22. August 2009, 13:07
Dein Code geht bei mir nicht, kommen unmengen an Fehlern beim
komplimieren, liegt vielleicht daran das du einen anderen Compiler
als ich verwendest.
Er benutzt die Datentypen aus stdint.h, die du vermutlich nicht definiert hast.

Womit wir wieder bei einer Grundregel wären: Beherrsche die Sprache, mit der du ein OS entwickeln willst. Ein OS ist schwierig genug, dass man nicht auch noch mit der Sprache kämpfen müssen sollte. Und noch viel wichtiger: Verstehe Beispielcode anstatt ihn zu kopieren. Dann hättest du nämlich kein Problem damit, ihn auf deinen Code anzupassen.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 13:23
typedef struct {
uint16_t  offset_low;
uint16_t selector;
uint8_t zero;
uint8_t attribute;
uint16_t offset_high;
}id_table;

id_table IDT[256];

void begin() {
idt_set_gate(0, (unsigned)intr_0, 0x16, IDT_STD_GATE);
}

void idt_set_gate(uint16_t num, uint32_t base, uint16_t sel, uint8_t attr) {
IDT[num].offset_low = (base & 0xFFFF);
IDT[num].offset_high = (base >> 16) & 0xFFFF;
IDT[num].selector = sel;
IDT[num].zero = 0;
IDT[num].attribute = attr;

struct {
unsigned int limit;
unsigned int base;
}  __attribute__((packed)) idt_ptr = {
.limit  = 256*8 - 1,
.base  = (unsigned int)IDT,

};

asm("lidt %0" : : "m" (idt_ptr));
}

So?
Titel: Re: IDT funktioniert nicht
Beitrag von: kevin am 22. August 2009, 13:45
Ich glaube, es bewegt sich langsam in die richtige Richtung. 0x16 sollte aber num sein, nicht sel. sel ist der Selektor für dein Codesegment, also vermutlich 0x08.

Außerdem brauchst du die IDT nicht bei jedem Eintrag, den du neu setzt, laden. Normalerweise setzt du einfach erst alle Einträge und lädst dann hinterher die IDT, die du aufgebaut hast.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 14:00
Was muss ich einbinden damit (unsigned)intr_0 funktioniert?
Und ich bin mir nicht sicher ob 0x08 mein Codesegment ist....
Titel: Re: IDT funktioniert nicht
Beitrag von: rizor am 22. August 2009, 14:13
Liegt deine Methode am Ende nicht im Kernel-Space?

Du kannst dir einfach eine ASM-Methode schreiben, die die interrupt-nummer und ggf. den errorcode auf den Stack pusht.
Danach kannst du einen handler aufrufen, der den letzten CPU-Status speichert und dann am Ende den Interrupt behandelt.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 14:16
Das Problem ist nur noch hier:

idt_set_gate(0x16, 0, 0x08, IDT_STD_GATE);
Beim 2. Parameter (uint32_t base) weiß ich nicht, was da hin soll.

Ja, ist im Kernelspace.
Titel: Re: IDT funktioniert nicht
Beitrag von: rizor am 22. August 2009, 14:19
Das ist genau deine Methode, die angesprungen werden soll, wenn der Interrupt ausgelöst wird.
Bei mir intr_0
Titel: Re: IDT funktioniert nicht
Beitrag von: Jidder am 22. August 2009, 14:21
Wobei für Interrupt 0x16 vielleicht der Name intr_0x16 oder intr_22 oder so angebracht ist.
Titel: Re: IDT funktioniert nicht
Beitrag von: rizor am 22. August 2009, 14:23
Stimmt, hab mich nur verlesen.
Dachte, dass es der 0. Interrupt ist
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 14:31
#define intr_16 0x16
idt_set_gate(0x16, (unsigned)intr_16, 0x08, IDT_STD_GATE);

Falsch oder?^^
Titel: Re: IDT funktioniert nicht
Beitrag von: rizor am 22. August 2009, 14:34
Ja, du musst dir methoden schreiben.
Ein makro könnte zum beispiel so aussehen:
.macro intr nr
.global intr_\nr
intr_\nr:
    pushl $0
    pushl $\nr
    jmp intr_handler
.endm
Dann definierst du in dem file einfach intr 22 und schon existiert die Methode intr_22
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 14:43
asm(".macro intr nr\n\t.global intr_\nr\n\tintr_\nr:\n\tpushl $0\n\tpushl $\nr\n\tjmp intr_handler\n\t.endm");

#define intr_22 ...

Mit welchem Wert soll ich das definieren?
Wenn ich #define ohne Wert mache kommt ein Fehler.
Titel: Re: IDT funktioniert nicht
Beitrag von: rizor am 22. August 2009, 14:49
Das kann auch nicht funktionieren.
Macro ist keine asm-befehl.
Das ist nur ein Platzhalter, der vom Compiler dann angepasst wird.
Wenn du als intr_22 eingibst, dann ersetzt der Compiler intr_22 durch das angepasste Macro.

Hier ist mein Interrupt-Handler:
.macro intr nr
.global intr_\nr
intr_\nr:
    pushl $0
    pushl $\nr
    jmp intr_handler
.endm

.macro intr_err nr
.global intr_\nr
intr_\nr:
    pushl $\nr
    jmp intr_handler
.endm

//the exceptions
intr 0
intr 1
intr 2
intr 3
intr 4
intr 5
intr 6
intr 7
intr_err 8
intr 9
intr_err 10
intr_err 11
intr_err 12
intr_err 13
intr_err 14
intr 15
intr 16
intr_err 17
intr 18
intr 19
intr 20
intr 21
intr 22
intr 23
intr 24
intr 25
intr 26
intr 27
intr 28
intr 29
intr 30
intr 31

//the IRQs
intr 32
intr 33
intr 34
intr 35
intr 36
intr 37
intr 38
intr 39
intr 40
intr 41
intr 42
intr 43
intr 44
intr 45
intr 46
intr 47

.extern intr_dispatcher
intr_handler:
    //safe the cpu-status
    push %ebp
    push %edi
    push %esi
    push %edx
    push %ecx
    push %ebx
    push %eax

//load kernel-data-segment
    mov $0x10, %eax
    mov %eax, %ds
    mov %eax, %es

    push %esp
    call intr_dispatcher //call the dispatcher
    mov %eax , %esp

    //load user-data-segment
    mov $0x23, %eax
    mov %eax, %ds
    mov %eax, %es

    //restore the cpu-status
    pop %eax
    pop %ebx
    pop %ecx
    pop %edx
    pop %esi
    pop %edi
    pop %ebp

    //skip the errorcode and the intr-nr
    add $8, %esp

    iret

Hoffe, dass das jetzt verständlicher ist.
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 14:59
intr_handler sollte dann eine Funktion aufrufen (logisch sonst tut sich ja nix). Das kannst du so machen:

Interrupts.c:
struct registers
{
    unsigned int gs, fs, es, ds;      //segmentregister
    unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
    unsigned int int_num, err_code;  //müssen von den Asm funktionen draufgepusht werden
    unsigned int eip, cs, eflags, useresp, ss;    //ACHTE AUF DIE REIHENFOLGE!!!
};

void *Interrupt_routines;

void install_handler(int interrupt, (*handler) (struct registers))
{
         interrupt_routines[interrupt] = handler;
}

void interrupt_handler(struct registers *reg)
{
    void (*handler)();

    handler = interrupt_routines[reg->int_num];
    if (handler)
    {
        handler(reg);
    }
}

int_num muss vom asm handler übergeben werden.
die entsprecehnde Funktion, welche vorher mit install_handler in die Tabelle eingefügt wurde wird dann aufgerufen.

den asm Code und das schreiben der Funktionen überlasse ich aber dir :-D.

EDIT: upps hab ja rizors ASM Code übersehen dann müsste meine interrupt handler Funktion intr_dispatcher(struct registers *regs) heissen.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 15:22
Hmm...sorry, aber mein Compiler kann euren Code nicht komplimieren,
da kommen immer unmengen an Fehlern, hab versucht die wegzumachen, ohne Erfolg :(.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 15:27
Oder ich schalte vor jeden Interrupt in den
Real Mode und danach wieder in den Protect Mode.
Ist zwar umständlich aber anders gehts nicht, oder?
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 15:36
Welchen Compiler und welchen assembler benutzt du denn und welche versionen?

Einige Fehler sind bei meinem Code bestimmt drin (ich habe den ja gerade rst geschrieben) aber die müsste man doch finden können?

einen fehler hab ich selber gesehen nachdem ich Gepostet habe:

void *Interrupt_routines klein schreiben. Ansonsten solltest du versuchen den asm code in nasm umzuwandeln und erst süäter mit dem linker einzubinden, da sich inline für solche aufgaben eher nocht eignet(also die $ Zeichen o.ä weglassen).

Und beschäftige dich mit dem Code. Versuch die Fehler zu finden und zu beheben, denn wenn du schon mit deinem Compiler kämfst wirst du sicher nicht weit kommen.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 15:42
Wo muss der Code von Rizor denn hin? Kann ja nur Assembler sein.

Edit:

GCC: 3.4.5
NASM: 2.07
Linker: 2.9.4
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 16:21
zum verstehen:

Ich hatte vorhin vergessen  die  Funktionen von rizor in meinen Code zu übernehmen, auch gefällt mir rizors Code nicht so ganz...sry rizor.

hier der Komplette Code:

Interrupts.c:
extern void intr1();
extern void intr2();
extern void intr3();
...         //schreib hier einfach die intrs aus dem asm code rein(extern nicht vergessen sonst werden die neu definiert!!!)
extern void intr47();


//Die Irqs müssen neu gemappt werden
void remap_irq(void)
{
    outb(0x20, 0x11);
    outb(0xA0, 0x11);
    outb(0x21, 0x20);
    outb(0xA1, 0x28);
    outb(0x21, 0x04);
    outb(0xA1, 0x02);
    outb(0x21, 0x01);
    outb(0xA1, 0x01);
    outb(0x21, 0x0);
    outb(0xA1, 0x0);
}


//muss irgendwo im Kernel aufgerufen werden, bevor Interrupts benutzt werden können
void install_interrupts()
{
       remap_irq();

       idt_set_gate(1, (unsigned)intr1, 0x08, 0x8E);
       idt_set_gate(2, (unsigned)intr2, 0x08, 0x8E);
       ...     //das machst du auch selber :-D
       idt_set_gate(47, (unsigned)intr47,0x08, 0x8E);
}



struct registers
{
    unsigned int gs, fs, es, ds;      //segmentregister
    unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
    unsigned int int_num, err_code;  //müssen von den Asm funktionen draufgepusht werden
    unsigned int eip, cs, eflags, useresp, ss;    //ACHTE AUF DIE REIHENFOLGE!!!
};

void *interrupt_routines;

void install_handler(int interrupt, (*handler) (struct registers))
{
        interrupt_routines[interrupt] = handler;
}

void interrupt_handler(struct registers *reg)
{
   void (*handler)();

   handler = interrupt_routines[reg->int_num];
   if (handler)
   {
       handler(reg);
   }

   //EOI an Master und wenn nötig an Slave pic senden
   if(reg->int_num >= 40)
   {
           outb(0xA0, 0x20);
   }
    outb(0x20, 0x20);
}

Interrupts.asm:
%macro intr 1
global intr%1
intr%1:
    push byte 0
    push byte %1
    jmp intr_handler
%endmacro

%macro intr_err 1
global intr%1
intr%1:
    push byte %1
    jmp intr_handler
%endmacro


//the exceptions
intr 0
intr 1
intr 2
intr 3
intr 4
intr 5
intr 6
intr 7
intr_err 8
intr 9
intr_err 10
intr_err 11
intr_err 12
intr_err 13
intr_err 14
intr 15
intr 16
intr_err 17
intr 18
intr 19
intr 20
intr 21
intr 22
intr 23
intr 24
intr 25
intr 26
intr 27
intr 28
intr 29
intr 30
intr 31

//the IRQs
intr 32
intr 33
intr 34
intr 35
intr 36
intr 37
intr 38
intr 39
intr 40
intr 41
intr 42
intr 43
intr 44
intr 45
intr 46
intr 47

global

intr_handler:
    pusha
    push ds
    push es
    push fs
    push gs
    mov ax, 0x10   ; Daten Descriptor
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov eax, esp
    push eax

    call interrupt_handler ;hier wird der c handler aufgerufen

    ; alle Werte der CPU wiederherstellen
    pop eax
    pop gs
    pop fs
    pop es
    pop ds
    popa
    add esp, 8     ; Gibt den Error Code an
    iret           ; "returned" die register: CS, EIP, EFLAGS, SS, und ESP


ACHTUNG!
Interrupts.c mit gcc und Interrupts.asm mit nasm Compilieren und assemblieren.

Das ist lediglich eine minimal lösung. Ich überlasse es dir noch ein wenig damit rumzuspielen und es noch einfacher und besser zu machen.
(Ich garantiere nicht für die richtigkeit meines Codes)


Gruss
DaCodaaa

Edit:
ich glaube rizor ist davon ausgegangen, dass du inline assembler meinst, da du nicht in Intel syntax(nasm) sondern in AT&T(gcc inline) gepostet hast.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 16:45
Erstmal vielen vielen Dank für den Code :-D.

Hab den Code erweitert/verbessert, komme aber bei manchen Sachen nicht weiter:

Interrupts.asm:66: warning: macro `global' exists, but not taking 0 parameters
Interrupts.asm:66: warning: label alone on a line without a colon might be in er
ror
Interrupts.asm:82: error: symbol `interrupt_handler' undefined
C:\Users\Pk3\Desktop\C_Kernel
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:92: error: syntax error before '(' token
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:92: error: syntax error before ')' token
C:\Users\Pk3\Desktop\C_Kernel\kernel.c: In function `interrupt_handler':
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:99: warning: dereferencing `void *' point
er
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:99: error: void value not ignored as it o
ught to be
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x18):kernel.c: undefined reference
 to `intr_dispatcher'

Ich hab "handler" so definiert:
unsigned int *handler
92 void install_handler(int interrupt, (*handler) (struct registers)) {
93 interrupt_routines[interrupt] = handler;
94 }
95
96 void interrupt_handler(struct registers *reg) {
97 void (*handler)();
98
99 handler = Interrupt_routines[reg->int_num];
100 if (handler) {
102 handler(reg);
103 }
104
105
106 //EOI an Master und wenn nötig an Slave pic senden
107 if(reg->int_num >= 40) {
108 outb(0xA0, 0x20);
109 }
110 outb(0x20, 0x20);
111 }

Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 17:31
Zitat
Erstmal vielen vielen Dank für den Code grin.
:wink:

Zitat
Interrupts.asm:66: warning: macro `global' exists, but not taking 0 parameters

hab ich in der eile vergessen : schreib in Zeile 66 (geile Zeolennummer fürn Fehler :wink:) extern interrupt_handler oder wenn du linux benutzt extern _interrupt_handler da hin.

Zitat
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:92: error: syntax error before '(' token
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:92: error: syntax error before ')' token

Schreib einfach ein void vor (*handler) dann gehts.

Schreib in der Funktion interrupt_handler bei der definition des Funktionspointers ein stuct registers *regs in die Klammern.

Zitat
unsigned int *handler
Wo hast du das hingeschrieben??

Sry das waren alles Flüchtigkeitsfehler :oops:.

Wenns immernoch nicht funktioniert poste nochmal die Fehlermeldung.
Titel: Re: IDT funktioniert nicht
Beitrag von: rizor am 22. August 2009, 17:33
Ich vermute mal, dass das an deinem Funktionskopf liegt.

@DaCodaaa:
Was hast du gegen meinen Code? ;)

Edit:
Ach Fehler schon erläutert...
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 17:39
Interrupts.asm:82: error: binary output format does not support external referen
ces
C:\Users\Pk3\Desktop\C_Kernel
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:90: error: syntax error before "registers
"
C:\Users\Pk3\Desktop\C_Kernel\kernel.c: In function `install_handler':
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:91: error: `interrupt_routines' undeclare
d (first use in this function)
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:91: error: (Each undeclared identifier is
 reported only once
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:91: error: for each function it appears i
n.)
C:\Users\Pk3\Desktop\C_Kernel\kernel.c: In function `interrupt_handler':
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:97: warning: dereferencing `void *' point
er
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:97: error: void value not ignored as it o
ught to be
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x18):kernel.c: undefined reference
 to `intr_dispatcher'

unsigned int handler (ohne Stern) habe ich ganz am Anfang definiert (also global)

Kernel.c
90 void install_handler(int interrupt, void (*handler) (stuct registers *regs)) {
91 interrupt_routines[interrupt] = handler;
92 }
93
94 void interrupt_handler(struct registers *reg) {
95 void (*handler)();
96
97 handler = Interrupt_routines[reg->int_num];
98 if (handler) {
99 handler(reg);
100 }
101
102 if(reg->int_num >= 40) {
103 outb(0xA0, 0x20);
104 }
105 outb(0x20, 0x20);
106 }

Interrupts.asm
82  call interrupt_handler
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 17:48
Du sollst ja auch nasm nicht dazu bringen ein binary auszugeben sondern ein Objekt, damit der linker danach den c und den asm code zusammenlinken kann.

nasm -f elf -o Interrupts_asm.o Interrupts.asm

gcc -O3 -ffreestanding -c -o Interrupts_c.o

ld -T link.ld -O 1




Warum hast du denn handler definiert?
Titel: Re: IDT funktioniert nicht
Beitrag von: kevin am 22. August 2009, 17:49
Versuch einfch mal, die Fehlermeldungen zu lesen und zu korrigieren, was der Compiler bemängelt... Ein Beispiel mach ich dir:
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:90: error: syntax error before "registers"Schauen wir mal: Was steht da vor dem register? Hm, ein "stuct". Was könnte daran wohl falsch sein? Da fehlt ein r.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 18:03
C:\Users\Pk3\Desktop\C_Kernel\kernel.c: In function `install_handler':
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:90: warning: dereferencing `void *' point
er
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:90: error: invalid use of void expression

C:\Users\Pk3\Desktop\C_Kernel\kernel.c: In function `interrupt_handler':
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:96: warning: dereferencing `void *' point
er
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:96: error: void value not ignored as it o
ught to be
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x18):kernel.c: undefined reference
 to `intr_dispatcher'

Vorhin musste ich "handler" definieren, jetzt gehts auch ohne,
also jetzt hab ichs weggelassen.

89 void install_handler(int interrupt, void (*handler) (struct registers *regs)) {
90 Interrupt_routines[interrupt] = handler;
91 }
92
93 void interrupt_handler(struct registers *reg) {
94 void (*handler)();
95
96 handler = Interrupt_routines[reg->int_num];
97 if (handler) {
98 handler(reg);
99 }
100
101 if(reg->int_num >= 40) {
102 outb(0xA0, 0x20);
103 }
104 outb(0x20, 0x20);
105 }

@taljeth Ja mach ich ja, nur das hab ich übersehen, thx^^
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 18:13
handler hättest du nie definieren dürfen, da der Funktionspointer so heisst; also: 2 mal Definiert, also: gcc steikt, also: kein Programm.

Zitat
c:90: warning: dereferencing `void *' point

wie wärs wenn du interrupt_routines berall klein schreibst so wie ich es definiert habe???


Zitat
undefined reference
to `intr_dispatcher'

da sagt dir dein linker soviel wie: hey du hast intr_dispatcher nicht geschrieben!!!(klar ich hab sie ja auch interrupt_handler getauft. :wink:
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 18:26
"intr_dispatcher" war nirgends zu finden, hab einfach die kernel.o gelöscht und weg war der Fehler.

Hier mal die ganze Kernel.c:

#include <stdint.h>
#include "hInit.h"

typedef struct {
uint16_t  offset_low;
uint16_t selector;
uint8_t zero;
uint8_t attribute;
uint16_t offset_high;
}id_table;

id_table IDT[256];

int begin() {
//idt_set_gate(0x16, (unsigned), 0x08, IDT_STD_GATE);

v_clear();

v_print("$3-=Xype=-", 0);
v_print("$2Willkommen!", 2);
i_getKey();
v_print(str_replace("Eingabe", "ga", ""), 3);

while(1);
}

extern void intr1();
extern void intr2();
extern void intr3();
extern void intr4();
extern void intr5();
extern void intr6();
extern void intr7();
extern void intr8();
extern void intr9();
extern void intr10();
extern void intr11();
extern void intr12();
extern void intr13();
extern void intr14();
extern void intr15();
extern void intr16();
extern void intr47();

void remap_irq(void) {
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);
}

void install_interrupts() {
remap_irq();

idt_set_gate(1, (unsigned)intr1, 0x08, 0x8E);
idt_set_gate(2, (unsigned)intr2, 0x08, 0x8E);
idt_set_gate(3, (unsigned)intr3, 0x08, 0x8E);
idt_set_gate(4, (unsigned)intr4, 0x08, 0x8E);
idt_set_gate(5, (unsigned)intr5, 0x08, 0x8E);
idt_set_gate(6, (unsigned)intr6, 0x08, 0x8E);
idt_set_gate(7, (unsigned)intr7, 0x08, 0x8E);
idt_set_gate(8, (unsigned)intr8, 0x08, 0x8E);
idt_set_gate(9, (unsigned)intr9, 0x08, 0x8E);
idt_set_gate(10, (unsigned)intr10, 0x08, 0x8E);
idt_set_gate(11, (unsigned)intr11, 0x08, 0x8E);
idt_set_gate(12, (unsigned)intr12, 0x08, 0x8E);
idt_set_gate(13, (unsigned)intr13, 0x08, 0x8E);
idt_set_gate(14, (unsigned)intr14, 0x08, 0x8E);
idt_set_gate(15, (unsigned)intr15, 0x08, 0x8E);
idt_set_gate(16, (unsigned)intr16, 0x08, 0x8E);
idt_set_gate(47, (unsigned)intr47,0x08, 0x8E);
}

struct registers {
unsigned int gs, fs, es, ds; // segmentregister
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
unsigned int int_num, err_code; // müssen von den Asm funktionen draufgepusht werden
unsigned int eip, cs, eflags, useresp, ss; //ACHTE AUF DIE REIHENFOLGE!!!
};

void *interrupt_routines;

void install_handler(int interrupt, void (*handler) (struct registers *regs)) {
interrupt_routines[interrupt] = handler;
}

void interrupt_handler(struct registers *reg) {
void (*handler)();

handler = interrupt_routines[reg->int_num];
if (handler) {
handler(reg);
}

if(reg->int_num >= 40) {
outb(0xA0, 0x20);
}
outb(0x20, 0x20);
}

void idt_set_gate(uint16_t num, uint32_t base, uint16_t sel, uint8_t attr) {
IDT[num].offset_low = (base & 0xFFFF);
IDT[num].offset_high = (base >> 16) & 0xFFFF;
IDT[num].selector = sel;
IDT[num].zero = 0;
IDT[num].attribute = attr;

struct {
unsigned int limit;
unsigned int base;
}  __attribute__((packed)) idt_ptr = {
.limit  = 256*8 - 1,
.base  = (unsigned int)IDT,

};

asm("lidt %0" : : "m" (idt_ptr));
}

#include "hString.h"
#include "hVideo.h"
#include "hInput.h"

Übrigen Fehler:
C:\Users\Pk3\Desktop\C_Kernel\kernel.c: In function `install_handler':
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:90: warning: dereferencing `void *' point
er
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:90: error: invalid use of void expression

C:\Users\Pk3\Desktop\C_Kernel\kernel.c: In function `interrupt_handler':
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:96: warning: dereferencing `void *' point
er
C:\Users\Pk3\Desktop\C_Kernel\kernel.c:96: error: void value not ignored as it o
ught to be
Titel: Re: IDT funktioniert nicht
Beitrag von: kevin am 22. August 2009, 18:37
Ich seh zwar nicht, wo da ein void* dereferenziert wird, aber interrupt_routines könnte man als Array von Funktionspointern deklarieren. Ich nehme jedenfalls an, das war gemeint.

void (*interrupt_routines)()[256];
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 18:48
@taljeth
So kann man es zwar auch machen, aber der fehler lag daran, dass er interrupt routines immer gross geschrieben hatte.
Ausserdem ist mir gerade aufgefallen, dass der Compiler wohl erwartet, dass man ein Array daraus macht:
void *interrupt_routines[256];        (vielleicht sollte man es noch mit 0 initialisieren?)


void kann man nämlich mit allem beschreiben (ints,longs,chars und Funktionspointern), daher war es sicherlich nicht falsch, falsch war eher, das Fehlende Array.

@Pk3
Es wäre mit sicherheit besser, wenn du die IDT nicht im Kernel Code aufstellen würdest, sondern in einer anderen Datei und dann in einer header datei die Prototypen mit extern davor reinschreibst, welche dann im Kernel.c nutzbar wären.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 18:57
void *interrupt_routines[256]So gehts  :-).

Jetzt nurnoch ein Fehler, der kommt aber vom Linker:
C:\Users\Pk3\Desktop\C_Kernel\Interrupts.o: file not recognized: File format not
 recognized

Linker.ld
INPUT("C:\Users\Pk3\Desktop\C_Kernel\kernel.o")
INPUT("C:\Users\Pk3\Desktop\C_Kernel\Interrupts.o")
ENTRY(_begin)
SECTIONS
{
  .text  0x1000 :
  {
    *(.text)
    *(.rdata)
    *(.rodata*)
  }
  .data  :
  {
    *(.data)
  }
  .bss  :
  {
    *(.bss)
  }
}

Aufruf:
nasm -f elf -o Interrupts.o Interrupts.asm
C:\cygnus\cygwin-b20\H-i586-cygwin32\bin\ld -O 1 -T C:\Users\Pk3\Desktop\C_Kernel\link.ld -o C:\Users\Pk3\Desktop\C_Kernel\kernel.bin
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 19:03
Hier meine link.ld:

OUTPUT_FORMAT("binary")
INPUT(...)
INPUT(...)
OUTPUT(C:\MeinOS\Neon.ker)
OUTPUT(A:\NEON.ker)
ENTRY(initial)

phys = 0x00100000;

SECTIONS
{
  .text phys : AT(phys)
  {
    code = .;
    *(.text)
    *(.rodata)
    . = ALIGN(4096);
  }
  .data : AT(phys + (data - code))
  {
    data = .;
    *(.data)
    . = ALIGN(4096);
  }
  .bss : AT(phys + (bss - code))
  {
    bss = .;
    *(.bss)
    . = ALIGN(4096);
  }
  end = .;
}

Versuchs damit.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 19:10
Geht net, vielleicht liegts an NASM, also wie ich den Assembler Code komplimiert habe?
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 19:17
Also bei mir Funztz prima.
vlt neue ver. von nasm runterladen?
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 19:23
Ich hab NASM 2.07, welche hast du?
Titel: Re: IDT funktioniert nicht
Beitrag von: Jidder am 22. August 2009, 19:24
Wenn du elf-Dateien erstellst, darfst du sie nicht mit dem cygwin ld linken. Erstell mit NASM die Dateien im Format win32 oder coff. Oder Wechsel zu einem Cross Compiler.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 19:34
Habs mit "coff" gemacht.
nasm -f coff -o Interrupts.o Interrupts.asm
Linker.ld
INPUT("C:\Users\Pk3\Desktop\C_Kernel\Interrupts.o")
INPUT("C:\Users\Pk3\Desktop\C_Kernel\kernel.o")
ENTRY(_begin)
SECTIONS
{
  .text  0x1000 :
  {
    *(.text)
    *(.rdata)
    *(.rodata*)
  }
  .data  :
  {
    *(.data)
  }
  .bss  :
  {
    *(.bss)
  }
}

make.bat
ECHO OFF
nasm -f bin -o boot.bin boot.asm
nasm -f coff -o Interrupts.o Interrupts.asm

cd C:
cd C:\cygnus\cygwin-b20\H-i586-cygwin32\bin\

echo Compiling Kernel...
D:\Programme\CodeBlocks\MinGW\Bin\gcc -O3 -ffreestanding -m32 -fleading-underscore -c -o C:\Users\Pk3\Desktop\C_Kernel\kernel.o C:\Users\Pk3\Desktop\C_Kernel\kernel.c
echo Linking...
C:\cygnus\cygwin-b20\H-i586-cygwin32\bin\ld -O 1 -T C:\Users\Pk3\Desktop\C_Kernel\link.ld -o C:\Users\Pk3\Desktop\C_Kernel\kernel.bin
echo Convert binary...
C:\cygnus\cygwin-b20\H-i586-cygwin32\bin\objcopy -O binary C:\Users\Pk3\Desktop\C_Kernel\kernel.bin
echo Make Image...
copy /b C:\Users\Pk3\Desktop\C_Kernel\boot.bin + C:\Users\Pk3\Desktop\C_Kernel\Interrupts.bin + C:\Users\Pk3\Desktop\C_Kernel\kernel.bin C:\Users\Pk3\Desktop\C_Kernel\os.img

xcopy C:\Users\Pk3\Desktop\C_Kernel\os.img D:\Programme\Bochs-2.3.5\os.img /Y

pause

C:\Users\Pk3\Desktop\C_Kernel\rawwritewin.exe C:\Users\Pk3\Desktop\C_Kernel\os.img a:


Meldungen:
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x1b7):kernel.c: undefined referenc
e to `outb'
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x1cc):kernel.c: undefined referenc
e to `outb'
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x1e1):kernel.c: undefined referenc
e to `outb'
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x1f6):kernel.c: undefined referenc
e to `outb'
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x20b):kernel.c: undefined referenc
e to `outb'
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x220):kernel.c: more undefined ref
erences to `outb' follow
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x2e6):kernel.c: undefined referenc
e to `intr1'
C:\Users\Pk3\Desktop\C_Kernel\kernel.o(.text+0x327):kernel.c: undefined referenc
e to `intr2'....

Irgentwie wird die Assembler - Datei (Interrupts.asm) nicht mit "kernel.c"
verknüpft....

Titel: Re: IDT funktioniert nicht
Beitrag von: Jidder am 22. August 2009, 19:49
Hast du outb irgendwo definiert?

Du musst außerdem wenn du einen Assembler/Compiler für Windows benutzt im Assemblercode immer Unterstriche vor die Symbole, die aus C sichtbar sind, setzen.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 19:52
"outb" ist nirgends im Assembler Code zu finden, aber "intr" schon.

Welche Symbole?
Titel: Re: IDT funktioniert nicht
Beitrag von: Jidder am 22. August 2009, 20:11
Symbole nennt man die Funktionsnamen, und Variablennamen.

Dann musst du eine Funktion outb schreiben. Oder du nimmst die Funktion aus dem Wiki (http://lowlevel.brainsware.org/wiki/index.php/Teil_5_-_Interrupts):
static inline void outb(unsigned short port, unsigned char data)
{
    asm volatile ("outb %0, %1" : : "a" (data), "Nd" (port));
}
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 20:26
Danke, das mit outb klappt jetzt  :-), nur das mit dem Unterstrich noch net  :-(.

Muss ich das so machen?

Interrupts.asm
intr_0
intr_1
intr_2
...
Titel: Re: IDT funktioniert nicht
Beitrag von: kevin am 22. August 2009, 20:27
Ausserdem ist mir gerade aufgefallen, dass der Compiler wohl erwartet, dass man ein Array daraus macht:
void *interrupt_routines[256];        (vielleicht sollte man es noch mit 0 initialisieren?)
Ja, der entscheidende Fehler ist, dass es kein Array war. Aber wenn ich nicht sehr danebenliege, funktioniert void* zwar mit gcc, ist aber eigentlich falsch.  Objektzeiger und Funktionszeiger sind zwei verschiedene Sachen.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 20:51
Es ist nur noch dieser Fehler, wenn der weg ist, klappts endlich.
Wo genau muss ich im Assembler Code die Unterstriche setzen?
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 21:08
Zitat
Du musst außerdem wenn du einen Assembler/Compiler für Windows benutzt im Assemblercode immer Unterstriche vor die Symbole, die aus C sichtbar sind, setzen.

bei mir funktionierts zwar ohne, aber probieren geht über studieren also:

in dem Fall müsstest du im C-code vor jedem intr ein _ setzen:

extern void _intr1();
...

auch beim späteren gebrauch musst du den Strich davor setzen:

idt_set_gate(1,(unsigned)_intr(),...

im asm-code musst du ebenfalls nach dem extern ein _ setzen:

extern _interrupt_handler

und:

...
call _interrupt_handler
...


Wie gesagt, ich brauchs auf win nicht, desshalb kann ich mir nicht so wirklich vorstellen, dass es bei dir klappt.
Du könntest auch gucken, was gcc und nasm mit deinen Symbolen machen. Dafür musst du mit einem Editor die o-Datei öffnen und nachschauen wie die Symbole da heissen.

Aber wir werden ganz bestimmt in Zukunft nicht mehr die ganze Arbeit für dich machen(ein bisschen must du ja auch selber schreiben). Ausserdem hab ich manchmal auch genug probleme mit meinem eigenen OS(momentan diese verdammte Tastatur :x), sodass ich wirklich nicht jedem seinen code aufräumen kann.
Die anderen sehen das bestimmt genauso.
Titel: Re: IDT funktioniert nicht
Beitrag von: Jidder am 22. August 2009, 21:13
In den C-Code müssen keine Unterstriche. Nur in den Assemblercode.
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 21:18
Das verwirrt mich jetzt ein bisschen :|.

Warum sollten denn in den asm-code unterstriche vor den namen und im C-code nich???? :?

Macht etwa gcc Unterstriche vor die Symbole??
Titel: Re: IDT funktioniert nicht
Beitrag von: Jidder am 22. August 2009, 21:21
Ja, unter Windows.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 21:22
Hab in der *.o Datei von Interrupts.asm nachgeschaut.
Nach dem ich in Interrupts.am vor jeder Variable ein _ habe
waren die in der *.o - Datei auch, und habe in kernel.o nachgeschaut
da waren die Unterstriche genauso, also müsste es passen.
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 21:26
@Pk3
Geile Seite hast du das alles alleine gemacht?
im Chat ist nur nich wirklich viel los...

Ich weiß ist offtopic. hoffe ihr verzeiht mir...
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 22. August 2009, 21:29
@DaCodaaa Thx, jo hab ich selber gemacht, ist aber noch net fertig  :-D
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 22. August 2009, 21:32
vlt Schreibe ich iwan auch mal so kleine Spiele
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 23. August 2009, 11:38
Habs jetzt hinbekommen, das Interrupts.asm mit "ELF" komplimiert wird und
der Linker das akzeptiert. Aber die Interrupts wollen immer noch nicht gehen :(, wenn ich jetzt

asm("sti");
am Ende der remap_irq - Funktion schreibe, dann sagt Bochs:

00004399371-i-@00001d72-[CPU0 ] >> mov byte ptr ds:[eax], 0x00 : C60000
00004399371-e-@00001d72-[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting

Wenn ich ein Interrupt ausführe, ohne das "sti", sagt Bochs wieder das
selbe wie am Anfang:

00008848368-i-@00001038-[CPU0 ] >> int 0x16 : CD16
00008848368-e-@00001038-[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting

Liegt das vielleicht daran?:

idt_set_gate(1, (unsigned)intr1, 0x08, 0x8E);
Hier nochmal der Code:

#include <stdint.h>
#include "hInit.h"

extern void intr0();
...
extern void intr47();

void install_interrupts();

int begin() {
install_interrupts();

v_clear();

v_print("$3-=Xype=-", 0);
v_print("$2Willkommen!", 2);
asm("int $0x16");
v_print(str_replace("Eingabe", "ga", ""), 3);

while(1);
}

static inline void outb(unsigned short port, unsigned char data) {
asm volatile ("outb %0, %1" : : "a" (data), "Nd" (port));
}

void remap_irq(void) {
outb(0x20, 0x11);
outb(0xA0, 0x11);
outb(0x21, 0x20);
outb(0xA1, 0x28);
outb(0x21, 0x04);
outb(0xA1, 0x02);
outb(0x21, 0x01);
outb(0xA1, 0x01);
outb(0x21, 0x0);
outb(0xA1, 0x0);
}

void install_interrupts() {
remap_irq();

idt_set_gate(0, (unsigned)intr0, 0x08, 0x8E);
idt_set_gate(1, (unsigned)intr1, 0x08, 0x8E);
idt_set_gate(2, (unsigned)intr2, 0x08, 0x8E);
...
idt_set_gate(47, (unsigned)intr47, 0x08, 0x8E);

struct {
unsigned int limit;
unsigned int base;
}  __attribute__((packed)) idt_ptr = {
.limit  = 256*8 - 1,
.base  = (unsigned int)IDT,

};

asm("lidt %0" : : "m" (idt_ptr));
}

struct registers {
unsigned int gs, fs, es, ds;
unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
unsigned int int_num, err_code;
unsigned int eip, cs, eflags, useresp, ss;
};

void *interrupt_routines[256];

void install_handler(int interrupt, void (*handler) (struct registers *regs)) {
interrupt_routines[interrupt] = handler;
}

void interrupt_handler(struct registers *reg) {
void (*handler)();

handler = interrupt_routines[reg->int_num];
if (handler) {
handler(reg);
}

if(reg->int_num >= 40) {
outb(0xA0, 0x20);
}
outb(0x20, 0x20);
}

void idt_set_gate(uint16_t num, uint32_t base, uint16_t sel, uint8_t attr) {
IDT[num].offset_low = (base & 0xFFFF);
IDT[num].offset_high = (base >> 16) & 0xFFFF;
IDT[num].selector = sel;
IDT[num].zero = 0;
IDT[num].attribute = attr;
}

#include "hString.h"
#include "hVideo.h"
#include "hInput.h"

Am Assembler - Code habe ich nur wie gesagt die Unterstriche
vor jedes "intr" und vor jede Funktion.
Titel: Re: IDT funktioniert nicht
Beitrag von: kevin am 23. August 2009, 12:24
   struct {
      unsigned int limit;
      unsigned int base;
   }
limit hat nur zwei Byte. Du nimmst vier Bytes dafür, deswegen kriegt er die falsche Basisadresse für deine IDT.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 23. August 2009, 12:29
Habs geändert, aber der Fehler ist immernoch der selbe  :-(.
Titel: Re: IDT funktioniert nicht
Beitrag von: Pk3 am 23. August 2009, 15:40
Jetzt gehts, hat am IDT - Pointer gelegen, vielen Dank an alle  :-D!
Titel: Re: IDT funktioniert nicht
Beitrag von: DaCodaaa am 23. August 2009, 16:11
 :-D