Asm volatile(" int $ 0x3")调用重启机器

时间:2014-08-19 00:35:23

标签: kernel interrupt-handling

我正在研究内核开发。要测试我的中断处理程序,我需要运行asm volatile(“idt $ 0x3”)命令。每当在main.c中调用此命令时,机器总是重新启动。我甚至试图删除中断处理程序。没有改变。我该怎么办?

gdt汇编:

[extern _start]

lgdt [gdt_descriptor]
jmp CODE_SEG:initgdt

initgdt:
mov ax, DATA_SEG     
mov ds, ax       
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov ebp, 0x90000
mov esp, ebp
call _start ;main.c function
jmp $

gdt_star:

gdt_null:
dd 0x0      
dd 0x0      

gdt_code:
dw 0xffff   
dw 0x0010
db 0x00     
db 10011011b
db 01001111b
db 0x00 

gdt_data:
dw 0xffff
dw 0x0020
db 0x00
db 10010010b
db 01001111b
db 0x0              


gdt_end:

gdt_descriptor:
dw gdt_end - gdt_star - 1
dd gdt_star

CODE_SEG equ gdt_code - gdt_star
DATA_SEG equ gdt_data - gdt_star

descriptor_tables.c:

extern void idt_flush(uint32_t);
extern void isr0();
extern void isr1();
....
extern void isr31();


static void init_idt()
{
    idt_ptr.limit = sizeof(idt_entry_t) * 256 -1;
    idt_ptr.base  = (uint32_t)&idt_entries;

    memset((uint8_t*)&idt_entries, 0, sizeof(idt_entry_t)*256);

    idt_set_gate(0, (uint32_t)isr0, 0x08, 0x8E);
    idt_set_gate(1, (uint32_t)isr1, 0x08, 0x8E);
    ....
    idt_set_gate(31, (uint32_t)isr31, 0x08, 0x8E);

    idt_flush((uint32_t)&idt_ptr);
}

static void idt_set_gate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags)
{
   idt_entries[num].base_lo = base & 0xFFFF;
   idt_entries[num].base_hi = (base >> 16) & 0xFFFF;

   idt_entries[num].sel     = sel;
   idt_entries[num].always0 = 0;
   idt_entries[num].flags   = flags
}

interrupt.asm:

%macro ISR_NOERRCODE 1 
  [GLOBAL _isr%1]       
  _isr%1:
    cli
    push byte 0
    push byte %1
    jmp isr_common_stub
%endmacro

%macro ISR_ERRCODE 1
  [GLOBAL _isr%1]
  _isr%1:
    cli
    push byte %1
    jmp isr_common_stub
%endmacro

ISR_NOERRCODE 0
ISR_NOERRCODE 1
....
ISR_NOERRCODE 31

[EXTERN _isr_handler]

isr_common_stub:
pusha                    

mov ax, ds               
push eax                

mov ax, 0x10 
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

call _isr_handler

pop eax        
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

popa                    
add esp, 8     
sti
iret  

isr.c:

void isr_handler(registers_t regs)
{
   uint8_t str[12] = "\ninterrupt:";
   str[11] = 0;
   puts(str, FALSE);
   itoa(str, 10, regs.int_no);
   puts(str, FALSE);
   str[0] = '\n';
   str[1] = 0;
   puts(str, TRUE);
}

kernel_entry.asm:

....
[global _idt_flush]
_idt_flush:
   mov eax, [esp+4]  
   lidt [eax]       
   ret

1 个答案:

答案 0 :(得分:0)

我将descriptor_tables.c C代码转换为汇编代码并使用以下宏:

%macro IDT_ENTRY 1
dw _isr%1
dw 0x08
db 0x0
db 0x8E
dw 0x0000
%endmacro

现在,它有效。但我不确定为什么它不接受C代码。此外,以下宏也不起作用:

%macro IDT_ENTRY 1
dw (_isr%1 - $$) & 0xFFFF
dw 0x08
db 0x0
db 0x8E
dw ((_isr%1 - $$) >> 16) & 0xFFFF
%endmacro

同样,我不确定为什么第二个宏不起作用。