assembly bochs:fetch_raw_descriptor:GDT:指数(bf)17 >极限(17)

sycxhyv7  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(92)

我正在尝试做一个简单的操作系统,我目前正在研究中断和IDT。
所以我实现了IDT和一个默认的异常处理程序,它目前什么也不做。
当我在bochs中运行我的操作系统时,我看到操作系统在跳转到内核时出现了三重错误。
bochs日志:

fetch_raw_descriptor: GDT: index (bf) 17 > limit (17)
interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
interrupt(): gate descriptor is not valid sys seg (vector=0x08)

字符串
异常0x0d是一般保护故障,所以我猜它与GDT有关,所以这里是我的GDT代码以及我如何加载它:

LoadGDT:
    lgdt [g_GDTDesc]
    ret

g_GDT:
    ; NULL descrytpor
    dq 0

    ; 32 code segment
    dw 0FFFFh                   ; limit
    dw 0                        ; base
    db 0                        ; base
    db 10011010b                ; access
    db 11001111b                ; granularity
    db 0                        ; base high

    ; 32 data segment
    dw 0FFFFh                   ; limit
    dw 0                        ; base
    db 0                        ; base
    db 10010010b                ; access
    db 11001111b                ; granularity
    db 0                        ; base high

g_GDTDesc:
    dw g_GDTDesc - g_GDT - 1    ; size of gdt
    dd g_GDT                    ; address of gdt


但如果是因为IDT,那么我就遵循osDev wiki的this教程。
idt.c:

#define INTERRUPT_GATE_FLAGS 0x8e
typedef struct {
    u16     isr_low;            // lower 16 bit of ISR's address
    u16     kernel_cs;          // gdt segment selector
    u8      reserved;           // set to zero
    u8      flags;              // attribute flags
    u16     isr_high;           // higher 16 bit of ISR's address
} PACKED idt_entry_t;

typedef struct {
    u16     limit;
    u32     ptr;
} PACKED idtr_t;

__attribute__((aligned(0x10))) static idt_entry_t idt[256];
static idtr_t idtr;

void exception_handler(){
    __asm__ volatile("cli; hlt"); // currently doe's nothing
}

void IDT_set_descriptor(u8 interrupt, void* isr, u8 flags){
    idt_entry_t* descriptor = &idt[interrupt];

    descriptor->isr_low     = (u32)isr & 0xFFFF;
    descriptor->kernel_cs   = 0x08;
    descriptor->reserved    = 0;
    descriptor->flags       = flags;
    descriptor->isr_high    = ((u32)isr >> 16) & 0xFFFF;
}

extern void* isr_stub_table[];
void IDT_init(){
    idtr.ptr = (u32)&idt[0];
    idtr.limit = (u16)sizeof(idt) - 1;

    for(u8 interrupt=0; interrupt<32; interrupt++){
        IDT_set_descriptor(interrupt, isr_stub_table[interrupt], INTERRUPT_GATE_FLAGS);
    }

    __asm__ volatile("lidt %0": :"m"(idtr));
    STI();
}


idt.asm:

; exceptions with error code
%macro isr_err_stub 1
isr_stub_%+%1:
    call exception_handler
    iret
%endmacro

; exceptions without error code
%macro isr_no_err_stub 1
isr_stub_%+%1:
    call exception_handler
    iret
%endmacro

extern exception_handler
isr_no_err_stub 0
isr_no_err_stub 1
isr_no_err_stub 2
isr_no_err_stub 3
......
isr_no_err_stub 29
isr_err_stub    30
isr_no_err_stub 31

; defining the isr_stub_table
global isr_stub_table
isr_stub_table:
%assign i 0
%rep 32
    dd isr_stub_%+i
%assign i i+1
%endrep

rggaifut

rggaifut1#

正如Michael Petch指出的,我的代码有两个主要问题。
第一个问题是,在我的 Boot 加载程序中,我只加载了一个扇区,尽管我的内核比这个扇区大。
第二个是在link.ldt中,我的链接脚本,我有:

.entry              : { __entry_start = .;      *(.entry)   }
 .text               : { __text_start = .;       *(.text)    }

字符串
这意味着.entry段将在.text段之前被链接。
但是在kernel_entry.asm中,这是一个调用主内核函数的文件,我从.text开始,所以我的内核没有正确链接。

相关问题