我正在使用https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf作为我的教科书从头开始编写基本内核 . 我已经编写了基本的16位引导加载程序,我只是根据本文编写了切换到保护模式的代码 . 它定义了一个基本的通用描述符表,加载它,并在cr0特殊寄存器中翻转一下 . 但是,当我尝试启动代码时,我会在屏幕底部反复出现光标 . 我可以't understand because I haven' t显示任何内容 . 当我试图显示一个字符串时,我只得到了屏幕底部的光标 . 这是我的一些代码 .

BITS 16
; switch to 32 bit protected mode
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

    ;mov ebp, 0x90000
    ;mov esp, ebp

BEGIN_PM:
    ;mov ebx, 0xb8000
    ;mov ah, 0x0f
    ;mov al, '3'
    ;mov [ebx], ax
    ;add ebx, 2
    ;mov al, '2'
    ;mov [ebx], ax
    jmp $

这是切换的部分 . 它从主boot_loader文件中调用 . 如果需要该代码,我可以编辑我的问题以包含它 . 感谢你们 . 我真的无法弄清楚问题,但这是我第一次编写32位启动加载程序 .

boot_loader.asm:

BITS 16
[org 0x7c00]

start:
    mov [BOOT_DRIVE], dl

    mov bp, 0x9000 ; setup our stack
    mov sp, bp

    mov dl, [BOOT_DRIVE]
    call disk_load
    call switch_to_pm

    jmp $


disk_load:
    push dx
    mov bx, 0x1000 ; adress to write to
    mov dh, 15     ; # sectors to read
    mov ah, 0x02   ; sector to start at ??
    mov al, dh     ; same # sectors
    mov ch, 0x00   ; cylinder to read ?
    mov dh, 0x00   ; head to read (switch?)
    mov cl, 0x02   ; sector to start at ??

    int 0x13

    jc disk_error

    pop dx
    cmp dh, al
    jne disk_error
    ret

disk_error:
    mov ah, 0x0e
    mov bx, DISKERR
    sub bx, 1
disk_error_print:
    add bx, 1
    cmp byte [bx], 0x0
    je disk_error_done
    mov al, [bx]
    int 0x10
    jmp disk_error_print
disk_error_done:
    jmp $


%include "boot/gdt.asm"
%include "boot/switch_to_pm.asm"


; Global vars
BOOT_DRIVE: db 0
DISKERR:
    db "error reading disk" , 0
; Bootsector padding
times 510-($-$$) db 0
dw 0xaa55
db "hello"

gdt.asm:

gdt_start:

gdt_null:
    dd 0x0
    dd 0x0
gdt_code: ; the code segment descriptor
    dw 0xffff
    dw 0x0
    dw 0x0
    db 10011010b
    db 11001111b
    db 0x0
gdt_data: ; the data segment descriptor
    dw 0xffff
    dw 0x0
    dw 0x0
    db 10010010b
    db 11001111b
    db 0x0
gdt_end:

gdt_descriptor:
dw gdt_end - gdt_start - 1
dd gdt_start

CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start