我正在尝试编写一个内核,主要是出于娱乐目的,并且我遇到了一个问题,因为我认为它是三重错误。在尝试启用分页之前,一切正常。破坏的代码是这样的:

void switch_page_directory(page_directory_t *dir){

 current_directory = dir;
 asm volatile("mov %0, %%cr3":: "r"(&dir->tablesPhysical));

 u32int cr0;
 asm volatile("mov %%cr0, %0": "=r"(cr0));

 cr0 |= 0x80000000;//enable paging
 asm volatile("mov %0, %%cr0":: "r"(cr0)); //this line breaks


}//switch page directory

为此,我一直在关注各种教程/文档,但是我用来分页的是http://www.jamesmolloy.co.uk/tutorial_html/6.-Paging.html。我不确定还有什么其他代码可以帮助您解决这一问题,但是如果有更多我应该提供的代码,我将非常乐意这样做。

编辑=====

我相信CS,DS和SS会选择正确的条目,这是用于设置它们的代码
global gdt_flush
extern gp
gdt_flush:

    lgdt [gp]        ; Load the GDT with our 'gp' which is a special pointer
    mov ax, 0x10      ; 0x10 is the offset in the GDT to our data segment

    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov ss, ax

    jmp 0x08:flush2   ; 0x08 is the offset to our code segment: Far jump!

flush2:
    ret               ; Returns back to the C code!

这是gdt结构本身
struct gdt_entry{
    unsigned short limit_low;
    unsigned short base_low;
    unsigned char base_middle;
    unsigned char access;
    unsigned char granularity;
    unsigned char base_high;
} __attribute__((packed));

struct gdt_ptr{
    unsigned short limit;
    unsigned int base;
} __attribute__((packed));

struct gdt_entry gdt[5];
struct gdt_ptr gp;

IDT与此非常相似。

最佳答案

GDT:您没有说出GDT条目的内容是什么,但是您显示的内容看起来与earlier part of the tutorial you linked to非常相似,如果您以相同的方式设置条目,那么一切都应该很好(即平面段映射,其中CS的环0代码段,其他所有环0数据段,都以0为基数,限制为4GB。

IDT:如果禁用了中断并且您还没有想到会导致页面错误,那么无论如何都可能无关紧要。

页表:不正确的页表似乎最有可能被怀疑。确保您的身份映射至少覆盖了您正在使用的所有代码,数据和堆栈内存。

链接到http://www.jamesmolloy.co.uk/tutorial_html/6.-Paging.html底部的源代码肯定可以构建可以在QEMU和Bochs上正常使用的东西,因此希望您可以将自己的工作与正在做的事情进行比较,并找出问题所在。

QEMU通常很好,但是我建议使用Bochs来开发真正的低级内容-它包含(或可以配置为包含)非常方便的internal debugger。例如在配置文件的reset_on_triple_fault=0行上设置cpu:,在switch_page_directory()代码中设置一个断点,运行到该断点,然后单步说明并查看会发生什么情况...

10-01 15:13