C语言 键盘在长模式下中断.64位操作系统



我尝试使用不同的教程从零开始创建我的第一个操作系统。现在我有一个简单的内核,具有简单的分页,64位的GDT,并进入长模式。但是键盘中断有一个问题。我读了很多关于这个的话题,我认为这是一个双重错误,当开始打字。请帮助我理解并解决这个问题。这里是仓库与我的代码https://github.com/alexanderian76/TestOS所以,问题是如果我输入任何东西,QEMU重置系统,而不是显示符号。据我所知,每次中断都会重置它。这是我的gdt64,进入长模式


gdt64:
dq 0 ; zero entry
.code: equ $ - gdt64 ; new
dq (1<<43) | (1<<44) | (1<<47) | (1<<53) ; code segment
.pointer:
dw $ - gdt64 - 1
dq gdt64

进入长模式。

start:
mov esp, stack_top
call check_multiboot
call check_cpuid
call check_long_mode
call set_up_page_tables ; new
call enable_paging     ; new
; print `OK` to screen
mov dword [0xb8000], 0x2f4b2f4f

lgdt [gdt64.pointer]
jmp gdt64.code:long_mode_start

hlt

long_mode_start:
; print `OKAY` to screen
mov ax, 0
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax

mov rax, 0x2f592f412f4b2f4f
mov qword [0xb8000], rax

call main

hlt

这是IDT

#define PIC2_COMMAND 0xA0
#define PIC2_DATA 0xA1
#define ICW1_INIT 0x10
#define ICW1_ICW4 0x01
#define ICW4_8086 0x01

struct IDT_entry {
unsigned short offset_lowerbits;
unsigned short selector;
unsigned char ist;
unsigned short offset_mid;
unsigned int zero;
unsigned char type_attr;
unsigned int offset_higherbits;
};
//*********************************

extern struct IDT_entry IDT[IDT_SIZE];
void load_idt_entry()
{
for(unsigned long long int t = 0; t < 256; t++) {
IDT[t].offset_lowerbits = (unsigned short)(((unsigned long long int)&isr1 & 0x000000000000ffff));
IDT[t].offset_mid = (unsigned short)(((unsigned long long int)&isr1 & 0x00000000ffff0000) >> 16);
IDT[t].offset_higherbits = (unsigned int)(((unsigned long long int)&isr1 & 0xffffffff00000000) >> 32);
IDT[t].selector = 0x08;
IDT[t].type_attr = 0x8e;
IDT[t].zero = 0;
IDT[t].ist = 0;


RemapPic();
outb(0x21, 0xfd);
outb(0xa1, 0xff);


LoadIDT();
}
}
void outb(unsigned short port, unsigned char val){
asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
}
unsigned char inb(unsigned short port){
unsigned char returnVal;
asm volatile ("inb %1, %0"
: "=a"(returnVal)
: "Nd"(port));
return returnVal;
}
void RemapPic(){
unsigned char a1, a2;
a1 = inb(PIC1_DATA);
a2 = inb(PIC2_DATA);
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
outb(PIC1_DATA, 0);
outb(PIC2_DATA, 8);
outb(PIC1_DATA, 4);
outb(PIC2_DATA, 2);
outb(PIC1_DATA, ICW4_8086);
outb(PIC2_DATA, ICW4_8086);
outb(PIC1_DATA, a1);
outb(PIC2_DATA, a2);
}

对不起,这是我第一次在这里问问题,但是我不能自己解决这个问题。非常感谢!

您的IDT_entry似乎有错误的顺序字段。type_attr应该在ist之后,zero应该在最后。另外,你的POPALL宏实际上有push而不是pop。

diff --git a/long_mode_init.asm b/long_mode_init.asm
index cd64e24..926afae 100644
--- a/long_mode_init.asm
+++ b/long_mode_init.asm
@@ -19,13 +19,13 @@ extern IDT
%endmacro

%macro POPALL 0
-    push r11
-    push r10
-    push r9
-    push r8
-    push rdx
-    push rcx
-    push rax
+    pop r11
+    pop r10
+    pop r9
+    pop r8
+    pop rdx
+    pop rcx
+    pop rax
%endmacro


diff --git a/main.c b/main.c
index b1bfa1c..22ef2fe 100644
--- a/main.c
+++ b/main.c
@@ -41,10 +41,10 @@ struct IDT_entry {
unsigned short offset_lowerbits;
unsigned short selector;
unsigned char ist;
-    unsigned short offset_mid;
-   unsigned int zero;
unsigned char type_attr;
+    unsigned short offset_mid;
unsigned int offset_higherbits;
+   unsigned int zero;
};
//*********************************

有了这些改变,它不再崩溃了。

最新更新