键盘在长模式下中断。 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;
};
//*********************************
通过这些更改,它不再崩溃。
我尝试使用不同的教程从 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;
};
//*********************************
通过这些更改,它不再崩溃。