中断三重故障
Triple fault on interrupts
我是新手,所以如果我错过了一些非常明显的事情,我提前道歉
所以,我试图在 x86 汇编和 C 中制作一个简单的内核。我试图让中断工作。我在汇编中定义了GDT、IDT。
我什至不确定是 GDT 还是 IDT 出了什么问题。问题是,在我真正触发中断之前,一切似乎都很好。
我查看了 OSDev、英特尔手册、James Molloy 的指南和随机博客文章,但我就是想不通。
代码如下:
; interrupts.asm
%macro ISRNOERR 1
isr%1:
cli
push byte 0
push byte %1
jmp isr_common_stub
isr%1_end:
%endmacro
%macro ISRERR 1
isr%1:
cli
push byte %1
jmp isr_common_stub
isr%1_end:
%endmacro
ISRNOERR 0
ISRNOERR 1
ISRNOERR 2
ISRNOERR 3
ISRNOERR 4
ISRNOERR 5
ISRNOERR 6
ISRNOERR 7
ISRERR 8
ISRNOERR 9
ISRERR 10
ISRERR 11
ISRERR 12
ISRERR 13
ISRERR 14
ISRNOERR 15
ISRNOERR 16
ISRNOERR 17
ISRNOERR 18
ISRNOERR 19
ISRNOERR 20
ISRNOERR 21
ISRNOERR 22
ISRNOERR 23
ISRNOERR 24
ISRNOERR 25
ISRNOERR 26
ISRNOERR 27
ISRNOERR 28
ISRNOERR 29
ISRNOERR 30
ISRNOERR 31
ISRNOERR 32
isr_common_stub:
pusha
mov ax, ds
push eax
mov ax, 0x10 ; Data segment descriptor (gdt.asm)
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
extern handler
call handler
pop eax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
popa
add esp, 8
sti
iret
; idt.asm
section .text
global _load_idt
_load_idt:
lidt [idt_info]
ret
%macro IRQ 1
irq%1:
dd isr%1
dw 0x0008
db 0x00
db 10101110b
dd isr%1_end
%endmacro
%include "interrupts.asm"
section .rodata
idt:
IRQ 0
IRQ 1
IRQ 2
IRQ 3
IRQ 4
IRQ 5
IRQ 6
IRQ 7
IRQ 8
IRQ 9
IRQ 10
IRQ 11
IRQ 12
IRQ 13
IRQ 14
IRQ 15
IRQ 16
IRQ 17
IRQ 18
IRQ 19
IRQ 20
IRQ 21
IRQ 22
IRQ 23
IRQ 24
IRQ 25
IRQ 26
IRQ 27
IRQ 28
IRQ 29
IRQ 30
IRQ 31
IRQ 32
idt_info:
dw idt_info - idt - 1
dd idt
// lime_main.c
#include <kernel/lime_tty.h>
extern void _load_gdt(); // From assembly
extern void _load_idt();
void lime_main()
{
lime_tty_init(TtyTextMode);
lime_tty_put_string("[ LIME ] Welcome to the Lime kernel!\n");
_load_gdt();
lime_tty_put_string("[ LIME ] Loaded GDT successfully!\n");
_load_idt();
lime_tty_put_string("[ LIME ] Loaded IDT successfully!\n");
asm ("int [=12=]x03"); // It's not crashing if I remove this
}
; gdt.asm
section .data
ALIGN 4
section .text
global _load_gdt
_load_gdt:
cli
lgdt [gdt_desc]
jmp 0x08:gdt_flush
gdt_flush:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
section .rodata
gdt:
gdt_null:
dd 0h
dd 0h
gdt_code:
dw 0FFFFh
dw 00000h
db 00h
db 10011010b
db 11001111b
db 0
gdt_data:
dw 0FFFFh
dw 00000h
db 00h
db 10010010b
db 11001111b
db 0
gdt_desc:
dw gdt_desc - gdt - 1
dd gdt
我同时在@MichaelPetch 的帮助下修复了它。基本上,正如他试图告诉我的那样,问题是我为 IDT 中的值定义了错误的大小。我正在为高位和低位定义双字 (dd),但我必须定义 16 位字 (dw)。
由于重定位问题,如果没有链接器脚本之类的东西,我无法真正静态地定义它。我试图避免这种情况,所以我最终采用了动态方法,我在 C 中做到了。
没有太多需要解释的地方,有很多我错过(或误解)的资源。
如果你像我一样是初学者,什么都不懂,我的建议是休息一下,然后带着新鲜的心态回来。 OSDev Wiki 将为您提供很多帮助(论坛也是)。
我是新手,所以如果我错过了一些非常明显的事情,我提前道歉
所以,我试图在 x86 汇编和 C 中制作一个简单的内核。我试图让中断工作。我在汇编中定义了GDT、IDT。
我什至不确定是 GDT 还是 IDT 出了什么问题。问题是,在我真正触发中断之前,一切似乎都很好。
我查看了 OSDev、英特尔手册、James Molloy 的指南和随机博客文章,但我就是想不通。
代码如下:
; interrupts.asm
%macro ISRNOERR 1
isr%1:
cli
push byte 0
push byte %1
jmp isr_common_stub
isr%1_end:
%endmacro
%macro ISRERR 1
isr%1:
cli
push byte %1
jmp isr_common_stub
isr%1_end:
%endmacro
ISRNOERR 0
ISRNOERR 1
ISRNOERR 2
ISRNOERR 3
ISRNOERR 4
ISRNOERR 5
ISRNOERR 6
ISRNOERR 7
ISRERR 8
ISRNOERR 9
ISRERR 10
ISRERR 11
ISRERR 12
ISRERR 13
ISRERR 14
ISRNOERR 15
ISRNOERR 16
ISRNOERR 17
ISRNOERR 18
ISRNOERR 19
ISRNOERR 20
ISRNOERR 21
ISRNOERR 22
ISRNOERR 23
ISRNOERR 24
ISRNOERR 25
ISRNOERR 26
ISRNOERR 27
ISRNOERR 28
ISRNOERR 29
ISRNOERR 30
ISRNOERR 31
ISRNOERR 32
isr_common_stub:
pusha
mov ax, ds
push eax
mov ax, 0x10 ; Data segment descriptor (gdt.asm)
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
extern handler
call handler
pop eax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
popa
add esp, 8
sti
iret
; idt.asm
section .text
global _load_idt
_load_idt:
lidt [idt_info]
ret
%macro IRQ 1
irq%1:
dd isr%1
dw 0x0008
db 0x00
db 10101110b
dd isr%1_end
%endmacro
%include "interrupts.asm"
section .rodata
idt:
IRQ 0
IRQ 1
IRQ 2
IRQ 3
IRQ 4
IRQ 5
IRQ 6
IRQ 7
IRQ 8
IRQ 9
IRQ 10
IRQ 11
IRQ 12
IRQ 13
IRQ 14
IRQ 15
IRQ 16
IRQ 17
IRQ 18
IRQ 19
IRQ 20
IRQ 21
IRQ 22
IRQ 23
IRQ 24
IRQ 25
IRQ 26
IRQ 27
IRQ 28
IRQ 29
IRQ 30
IRQ 31
IRQ 32
idt_info:
dw idt_info - idt - 1
dd idt
// lime_main.c
#include <kernel/lime_tty.h>
extern void _load_gdt(); // From assembly
extern void _load_idt();
void lime_main()
{
lime_tty_init(TtyTextMode);
lime_tty_put_string("[ LIME ] Welcome to the Lime kernel!\n");
_load_gdt();
lime_tty_put_string("[ LIME ] Loaded GDT successfully!\n");
_load_idt();
lime_tty_put_string("[ LIME ] Loaded IDT successfully!\n");
asm ("int [=12=]x03"); // It's not crashing if I remove this
}
; gdt.asm
section .data
ALIGN 4
section .text
global _load_gdt
_load_gdt:
cli
lgdt [gdt_desc]
jmp 0x08:gdt_flush
gdt_flush:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
section .rodata
gdt:
gdt_null:
dd 0h
dd 0h
gdt_code:
dw 0FFFFh
dw 00000h
db 00h
db 10011010b
db 11001111b
db 0
gdt_data:
dw 0FFFFh
dw 00000h
db 00h
db 10010010b
db 11001111b
db 0
gdt_desc:
dw gdt_desc - gdt - 1
dd gdt
我同时在@MichaelPetch 的帮助下修复了它。基本上,正如他试图告诉我的那样,问题是我为 IDT 中的值定义了错误的大小。我正在为高位和低位定义双字 (dd),但我必须定义 16 位字 (dw)。
由于重定位问题,如果没有链接器脚本之类的东西,我无法真正静态地定义它。我试图避免这种情况,所以我最终采用了动态方法,我在 C 中做到了。
没有太多需要解释的地方,有很多我错过(或误解)的资源。
如果你像我一样是初学者,什么都不懂,我的建议是休息一下,然后带着新鲜的心态回来。 OSDev Wiki 将为您提供很多帮助(论坛也是)。