键盘在长模式下中断。 64 位 os

Keyboard interrupts in long mode. 64 bit os

我尝试使用不同的教程从 0 创建我的第一个 os。现在我有一个简单的内核,带有简单的分页,64 位的 GDT,并进入长模式。但是键盘中断有一个问题。我阅读了很多关于此的主题,我认为在开始打字时这是一个双重错误。请帮助我理解并解决这个问题。这是代表os我的代码 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 宏实际上是推送而不是弹出。

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;
 };
 //*********************************

通过这些更改,它不再崩溃。