我正在研究内核开发。要测试我的中断处理程序,我需要运行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
答案 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
同样,我不确定为什么第二个宏不起作用。