跳转到保护模式正在重启 QEMU

问题描述

我已经成功地为实模式编写了代码。但麻烦始于 32 位保护模式。在跳转到保护模式之前,我使用 cli 禁用了中断, 使用lgdt 加载GDT在cr0 中设置32 位模式位。但是 QEMU 正在无限重启。以下是代码

boot.asm

[BITS 16]
            BOOTSEG equ 0x7c00
            DATASEG equ 0x07c0
            STACKSEG equ 0x17c0
            EXTRASEG equ 0x37c0
            STACKPOINT equ 0x0000

            BLACKONWHITE equ 0x0F
            YELLOWONBLUE equ 0x1E

            VIDEO_MEMORY equ 0xb8000

            global _start

_start:

            xor ax,ax

            mov ax,STACKSEG
            mov ss,ax              ;initializing stack segment
            mov sp,STACKPOINT
            
            mov ax,DATASEG
            mov ds,ax              ;initializing data segment

            mov ax,EXTRASEG
            mov es,ax               ;initializing extra segment

            call Switch_To_Pm

            %include "./screen.asm"
            %include "./lib.asm"
            %include "./gdt.asm"
            %include "./protected_mode/switch_to.asm"

[bits  32]

Begin_Pm:
            jmp $

            times 510 - ($ - $$) db 0

            dw 0xAA55

gdt.asm

gdt_start:

null_descriptor:
                dd 0x0
                dd 0x0

code_descriptor:
                dw 0xffff
                dw 0x0
                db 0x0
                db 10011010b
                db 11001111b
                db 0x0

data_descriptor:
                dw 0xffff
                dw 0x0
                db 0x0
                db 10010010b
                db 11001111b
                db 0x0

gdt_end:

gdt_descriptor:
                dw gdt_end - gdt_start - 1
                dd gdt_start

CODE_SEG equ code_descriptor - gdt_start

DATA_SEG equ data_descriptor - gdt_start

protected_mode/switch_to.asm

    [BITS 16]
Switch_To_Pm:
                cli
                lgdt [gdt_descriptor]
                mov eax,cr0
                or eax,0x1
                mov cr0,eax
                jmp CODE_SEG:Init_Pm

[BITS 32]

Init_Pm:
                mov ax,DATA_SEG
                mov ds,ax
                mov ss,ax
                mov es,ax
                mov fs,ax
                mov gs,ax

                call Begin_Pm

lib.asm 包含使用 int 0x15 的延迟例程,screen.asm 包含以实模式打印文本的 BIOS 例程。

以下是我用来构建的命令

nasm -fbin -o boot.bin boot.asm
qemu boot.bin

不知道为什么,QEMU 无限重启。代码直到实模式运行良好。可能是切换到保护模式有问题。

在此之前感谢任何帮助

解决方法

我想我已经确定了问题所在。问题出在线路上 jmp CODE_SEG:Init_Pm 中的 protected_mode/switch_to.asm。我应该向远跳添加一个 0x7c00 的偏移量。
相反,我使用了 [org 0x7c00] 并重写了实模式和保护模式代码,它奏效了。