为什么切换到保护会重启机器?

时间:2013-10-11 16:06:02

标签: assembly x86 intel qemu protected-mode

我正在尝试以64位创建非常简单的操作系统。我首先尝试进入保护模式,但此时我失败了。

当我跳远到32位时,机器重新启动。

我的代码被加载到内存中,另一个汇编程序位于地址0x100。

代码是用nasm编译的,我使用qemu -fda运行程序。

这是我到目前为止的代码:

[BITS 16]

jmp _start

_start:
    cli

    lgdt [GDT64]

    ; Switch to protected mode
    mov eax, cr0
    or al, 1b
    mov cr0, eax

    ; Desactivate pagination
    mov eax, cr0
    and eax, 01111111111111111111111111111111b
    mov cr0, eax

    jmp (CODE_SELECTOR-GDT64):pm_start

[BITS 32]

pm_start:
    jmp $

GDT64:
    NULL_SELECTOR:
        dw GDT_LENGTH   ; limit of GDT
        dw GDT64        ; linear address of GDT
        dd 0x0

    CODE_SELECTOR:          ; 32-bit code selector (ring 0)
        dw 0x0FFFF
        db 0x0, 0x0, 0x0
        db 10011010b
        db 11001111b
        db 0x0

    DATA_SELECTOR:          ; flat data selector (ring 0)
        dw  0x0FFFF
        db  0x0, 0x0, 0x0
        db  10010010b
        db  10001111b
        db  0x0

    LONG_SELECTOR:  ; 64-bit code selector (ring 0)
        dw  0x0FFFF
        db  0x0, 0x0, 0x0
        db  10011010b       ;
        db  10101111b
        db  0x0

   GDT_LENGTH:

如果我在跳远之前做jmp $,它可以正常停止,但是当跳远完成后,它会重新启动机器。

我是否忘记设置类似片段之类的内容?

1 个答案:

答案 0 :(得分:2)

正如您的评论所说,您需要GDT的线性地址。您似乎没有指定任何ORG指令,因此汇编程序将使用基址0,并且在运行时不会匹配该地址。

另外,不确定如何在0x100加载代码,引导扇区通常在0x7c00加载。

解决方案可以像在文件顶部指定ORG 0x7c00一样简单。