X86 设置全局描述符表和保护模式后持续重新启动

X86 设置全局描述符表和保护模式后持续重新启动,x86,bootloader,osdev,protected-mode,gdt,X86,Bootloader,Osdev,Protected Mode,Gdt,我一定是在GDT设置和切换到保护模式时出错了,因为它一直在重新启动 这是我的kernel.asm,它应该设置GDT并切换到保护模式: bits 16 jmp main %include "gdt.inc" main: cli xor ax,ax mov ds,ax mov es,ax mov ax,0x9000 mov ss,ax mov sp,0x

我一定是在
GDT设置
和切换到
保护模式
时出错了,因为它一直在重新启动

这是我的
kernel.asm
,它应该设置
GDT
并切换到
保护模式

    bits 16

    jmp main
    %include "gdt.inc"

    main:
        cli
        xor ax,ax
        mov ds,ax
        mov es,ax
        mov ax,0x9000
        mov ss,ax
        mov sp,0xffff
        sti

        call InstallGDT

        cli
        mov eax,cr0
        or eax,1
        jmp 08h:Stage3

    bits 32
    Stage3:

        mov ax,0x10
        mov ds,ax
        mov ss,ax
        mov es,ax
        mov esp,90000h

    Stop:

        mov byte [0xb8000],'A'
        cli
        hlt
还有gdt.inc的

bits 16
InstallGDT:

    cli
    pusha
    lgdt   [toc]
    sti
    popa
    ret
gdt_data:
    dd 0
    dd 0

    dw 0ffffh
    dw 0
    db 0
    db 10011010b
    db 11001111b
    db 0

    dw 0ffffh
    dw 0
    db 0
    db 10010010b
    db 11001111b
    db 0
end_of_gdt:
toc:
    dw end_of_gdt - gdt_data -1
    dd gdt_data
My
bootloader.asm
将10个扇区加载到
0x1000:0x000
,然后跳到那里

我使用以下命令测试代码:

nasm -f bin -o bootloader.bin bootloader.asm
nasm -f bin -o kernel.bin kernel.asm
cat bootloader.bin kernel.bin>OS.bin
qemu-system-i386 OS.bin

我的错在哪里?

因为我只能假设您已正确地将扇区读取到0x1000:0x0000的内存中,所以我只能指出
kernel.asm
gdt.inc
中的潜在问题


代码的问题 如果您使用
jmp 0x1000:0x0000
到达内核阶段(我怀疑是这种情况),那么在
kernel.asm
中,您错误地将DS和ES段寄存器设置为错误的值。在这种情况下,需要将这两个寄存器设置为0x1000,而不是0x0000。此代码:

    xor ax,ax
    mov ds,ax
    mov es,ax
需要更改为:

    mov ax,0x1000
    mov ds,ax
    mov es,ax

下一个主要问题是记录(在
toc
内)采用线性地址。实模式下的线性地址与物理地址是一样的。从说明集手册中可以看出:

源操作数指定一个6字节的内存位置,其中包含全局描述符表(GDT)的基址(线性地址)和限制(以字节为单位的表大小)

您为
kernel.asm
使用了一个0x0000的组织(因为您没有指定一个),因此NASM假设生成的所有偏移量都是从0x0000的基数开始的,包括标签
gdt\u数据。所以当你这样做的时候:

toc:
dw end_of_gdt - gdt_data -1
dd gdt_data
gdt_数据
将是略高于0x0000的一些小偏移量。在物理内存中,GDT记录实际上位于0x1000:0x0000+(小偏移量)。物理(线性)内存中的0x1000:0x0000为(0x1000
toc:
dw end_of_gdt - gdt_data -1
dd gdt_data+0x10000
    mov eax,cr0
    or eax,1
    mov eax,cr0
    or eax,1
    mov cr0, eax
jmp 08h:Stage3
jmp dword 08h:Stage3+0x10000