0

인터럽트 루틴이 호출되지 않아서 IDT가 작동하지 못합니다. 특히 키보드의 키를 누를 때 키보드 관련 문제가 발생합니다. IDT 테이블의 특수 48 비트 포인터의 주소를 전달합니다. 나는 또한 적어도 GDT가 작동 여부 모르는IDT가 C에서 작동하지 않습니다.

dt_ptr idt_ptr; // defining the pointer 
loadidt(dt_ptr *a); // how i am passing the pointer's address to assembly routine 

처럼 그 일을하고있다.

1) IDT를 작동 시키려면 어떻게해야합니까? 나는 약간의 튜토리얼도 보았지만 도움이되지 않았다. 2) GDT가 제대로 작동하는지 어떻게 확인할 수 있습니까?

미리 감사드립니다.

편집 : 내 자신의 OS 용으로 이것을하고 있습니다. 내 어셈블리 루틴이 포인터의 주소를 제대로 수신 할 수 있는지 의심 스럽다. 그래서 나는 또한 인라인 어셈블리를 사용하여 lidt를하려고했지만 도움이되지 않았습니다. 나는 무엇이 잘못되었는지 모른다. 어떤 단서, 생각?

void remap_irqs(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); 
outbyte('a'); 

}

void set_idt_gate(uint8 num, unsigned long base, word sel, uint8 flags) 
{ 
IDT[num].offset_low = (base & 0xFFFF); 
IDT[num].offset_high = (base >> 16) & 0xFFFF;  
IDT[num].selector = sel;  
IDT[num].zero = 0; 
IDT[num].type_attrs = flags; 
} 




void init_idt() 
{ 
outbyte('M'); 
idt_ptr.limit = (sizeof (idt_entry) * 256) - 1; 
idt_ptr.base =(uint32) &IDT; 

memset((uint8 *)&IDT, 0, sizeof(idt_entry) * 256); 
remap_irqs(); 
set_idt_gate(0, (unsigned) irq_0, 0x08, 0x8E); 
set_idt_gate(1, (unsigned) irq_1, 0x08, 0x8E); 
//install_isrs(); 
//install_irqs(); 
//idt_load(); 
//print_message(); 
lidt(&IDT,idt_ptr.limit); 
_LIDT(&idt_ptr); 
loadidt(&idt_ptr); 
} 



void lidt(void * base, unsigned short size) 
{ 
struct 
{ 
    unsigned short length; 
    unsigned long base; 
} __attribute__((__packed__)) IDTR; 

IDTR.length = size; 
IDTR.base = (unsigned long)base; 
asm("lidt (%0)" 
    : : "p"(&IDTR)); 

}

void _LIDT(dt_ptr *ptr) 
{ 
asm("lidt (%0)" : :"p"(ptr)); 
outbyte('n'); 
} 





void irq_0() 
{ 
//before_interrupt(); 
ticks+=1; 
if(ticks%18==0) 
{ 
    outbyte('+'); 
    outbyte('1'); 
} 
//after_interrupt(); 
} 

void irq_1() 
{ 
outbyte('a'); 
//before_interrupt(); 
irq1_keyb(); 
//after_interrupt(); 
} 

typedef struct { 
uint16 offset_low; // The lower 16 bits of the address to jump to when this 
interrupt occures:// offset 0-15 
uint16 selector;  // Kernel segment selector in IDT 
uint8 zero;   // This must always be zero. 
uint8 type_attrs; //gate types, atttribute types etc. 
uint16 offset_high; // The upper 16 bits of the address to jump to. offset 16-31 
} __attribute__((__packed__)) idt_entry; 


typedef struct { 
uint16 limit; 
uint32 base;  // The address of the first element in IDT array. 
} __attribute__((__packed__)) dt_ptr; 


global loadidt 
loadidt: 
push ebp 
mov ebp,esp  
mov eax,[ebp+8]  
lidt [eax]  
pop ebp  
ret 
+3

설명하여 플랫폼 및 어쩌면 운영 체제 – Matthias

+0

내 운영 체제 – geek1000

+0

... 및 플랫폼 (즉, 어떤 프로세서 및 인터럽트 고려 사항이있는 경우 컨트롤러가 인터럽트) – Matthias

답변

1

당신은 0x20 오프셋의 IRQ 벡터를 설정합니다. 즉, IRQ0이 인터럽트 0x20, IRQ1에 매핑되어 0x21 등으로 인터럽트됩니다. 그러나 인터럽트 0x000x01이 발생하면 irq 처리기가 실행되도록 설정합니다. . 그것은 당신이 설정하는 방법 IDR : 당신은 PIC here에 대한 자세한 정보를 찾을 수 있습니다

set_idt_gate(0x20, (unsigned) irq_0, 0x08, 0x8E); 
set_idt_gate(0x21, (unsigned) irq_1, 0x08, 0x8E); 

은 (섹션 초기화 그것을 말할 도움이 될 것입니다 정확히 당신이 remap_irqs 기능으로하고있는 인터럽트 문제에 대해서는

+0

감사합니다. gdt에 문제가있을 수 있습니다. 전반적으로 개선되지 않았습니다. – geek1000