2016-08-08 69 views
1

Ich versuche, die IDT meiner Kernel einzurichten, aber ich bin immer diese Verknüpfung Fehler:nasm Makro funktioniert nicht richtig

bin/obj/idt.o: In function `setup_idt': 
idt.c:(.text+0x9b): undefined reference to `interrupt_handler_1' 

Der Fehler sagt, dass interrupt_handler_1 nicht definiert, aber es ist ein Makro in interrupt_manager.asm:

%macro no_error_code_interrupt_handler 1 
global interrupt_handler_%1 
interrupt_handler_%1: 
    cli 
    push dword 0      ; push 0 as error code 
    push dword %1     ; push the interrupt number 
    jmp  common_interrupt_handler ; jump to the common handler 
%endmacro 

Hier ist die setyup_idt Funktion:

extern void interrupt_handler_1(); 

void setup_idt() 
{ 
    // Set the special idt_pointer 
    idt_pointer.limit = (sizeof(struct InterruptDescriptorTableEntry) * 256) - 1; // Subsract 1 because sizeof doesn't start from 0 
    idt_pointer.address = (uint32)&idt; 

    // Clear the whole idt to zeros 
    memset(&idt, 0, sizeof(struct InterruptDescriptorTableEntry) * 256); 

    for(unsigned int i = 0; i < 256; i++) 
    { 
     idt_set_gate(i, (uint32)&interrupt_handler_1, 0x8, 0x8E); 
    } 

    __asm__ __volatile__("lidt %0": :"m"(idt_pointer)); 

} 

Was habe ich falsch gemacht ?

Zusätzliche Frage: Gibt es einen Makro/andere Art und Weise automatisch den i Eintrag des GDT zu verknüpfen, um die i-Handler unterbrechen, lassen Sie mich versuchen, mich besser zu erklären:

Was ich will, ist so etwas zu tun :

for(unsigned int i = 0; i < 256; i++) 
    { 
     idt_set_gate(i, (uint32)&interrupt_handler_[i], 0x8, 0x8E); 
    } 

Wo interrupt_handler [i] den Interrupt handler_ wäre [i] durch die nasm Makro

+1

Linker sieht keine Makros. Verwenden Sie eine Funktion. –

+0

Makros sind nicht Teil des Codes, Sie müssen * das * Makro verwenden, damit es in tatsächlichen Code, der zusammengebaut wird, erweitert wird. –

+0

@Joachim Pileborg Okey, was ist mit der zusätzlichen Frage? –

Antwort

2

Sie müssen ersetzt werden würde das Makro in Ihrem NASM Code zu erweitern. Eine Makrodefinition selbst erzeugt keinen Code. Es muss explizit im NASM-Code verwendet werden.

Sie können die Anweisung %rep verwenden, um das Makro mit verschiedenen Parametern wiederholt zu erweitern. Etwas wie folgt aus:

extern common_interrupt_handler 

%macro error_code_interrupt_handler 1 
global interrupt_handler_%1 
interrupt_handler_%1: 
    push dword %1     ; push the interrupt number 
    jmp  common_interrupt_handler ; jump to the common handler 
%endmacro 

%macro no_error_code_interrupt_handler 1 
global interrupt_handler_%1 
interrupt_handler_%1: 
    push dword 0      ; push 0 as error code 
    push dword %1     ; push the interrupt number 
    jmp  common_interrupt_handler ; jump to the common handler 
%endmacro 

; Some CPU exceptions have error codes, some don't 

%assign intnum 0 
%rep 8 - intnum 
    no_error_code_interrupt_handler intnum 
    %assign intnum intnum + 1 
%endrep 

error_code_interrupt_handler 8 
no_error_code_interrupt_handler 9 

%assign intnum 10 
%rep 16 - intnum 
    error_code_interrupt_handler intnum 
    %assign intnum intnum + 1 
%endrep 

no_error_code_interrupt_handler 16 
error_code_interrupt_handler 17 
no_error_code_interrupt_handler 18 
no_error_code_interrupt_handler 19 
no_error_code_interrupt_handler 20 

%assign intnum 21 ; first (currently) unassigned CPU exception 
%rep 32 - intnum 
    no_error_code_interrupt_handler intnum 
    %assign intnum intnum + 1 
%endrep 

%assign intnum 32 ; first user defined interrupt 
%rep 256 - intnum 
    no_error_code_interrupt_handler intnum 
    %assign intnum intnum + 1 
%endrep 

; define a table of interrupt handlers for C code to use 

    global interrupt_handler_table 
interrupt_handler_table: 

%assign intnum 0 
%rep 256 
    dd interrupt_handler_ %+ intnum 
    %assign intnum intnum + 1 
%endrep 

Der obige Code eine Tabelle aller Interrupt-Handler erstellt, die Sie in Ihrem C-Code verwenden können:

extern uint32 interrupt_handler_table[256]; 

for(unsigned int i = 0; i < 256; i++) 
{ 
    idt_set_gate(i, interrupt_handler_table[i], 0x8, 0x8E); 
} 

Bitte beachte, dass ich ein error_code_interrupt_handler Makro erstellt haben für diese CPU-Ausnahmen, die Fehlercodes generieren. Außerdem habe ich den unnötigen CLI-Befehl aus Ihrem Code entfernt. Da Sie Interrupt-Gatter im IDT verwenden, wird das Interrupt-Enable-Flag automatisch gelöscht.

+0

Vielen Dank, das funktionierte perfekt für mich! –