首页 > 解决方案 > 为什么这个引导扇区只在 QEMU 中有效?

问题描述

我已经完成了相当多的研究并查看了类似的问题,但我似乎找不到任何有用的东西。我对此很陌生,但我对汇编代码中发生的事情及其原因有一个很好的理解。

基本上,这里的引导扇区在 QEMU 中运行得很好,但我的 PC 无法启动。它似乎陷入了一个循环,屏幕上只有闪烁的下划线。

MSG_REAL_MODE不会也不会MSG_PROT_MODE被打印到屏幕上(或者如果他们这样做,它们会立即被清除)。

这个有几个不同的文件。我知道这很多,对不起!如果您需要任何澄清,请告诉我:)

boot.asm(主引导文件)

[org 0x7c00]

  mov bp, 0x9000
  mov sp, bp
  
  mov bx, MSG_REAL_MODE
  call print_string
  
  call switch_to_pm
  
  jmp $
  
%include "f_print_string.asm"
%include "f_print_string_pm.asm"
%include "gdt.asm"
%include "f_switch_to_pm.asm"

[bits 32]
BEGIN_PM:

  mov ebx, MSG_PROT_MODE
  call print_string_pm
  
  jmp $
  
MSG_REAL_MODE: db "Started in 16-bit Real Mode", 0
MSG_PROT_MODE: db "Successfully landed in 32-bit Protected Mode", 0

times 510-($-$$) db 0
dw 0xaa55

f_print_string.asm(用于在 16 位实模式下打印字符串)

print_string:
  pusha
  
string_loop:
  mov al, [bx]
  cmp al, 0
  jne print_char
  popa
  ret
  
print_char:
  mov ah, 0x0e
  int 0x10
  add bx, 1
  jmp string_loop

f_print_string_pm.asm(用于在 32 位保护模式下打印字符串)

[bits 32]

VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f

print_string_pm:
  pusha
  mov edx, VIDEO_MEMORY
  
print_string_pm_loop:
  mov al, [ebx]
  mov ah, WHITE_ON_BLACK
  
  cmp al, 0
  je print_string_pm_done
  
  mov [edx], ax
  
  add ebx, 1
  add edx, 2
  
  jmp print_string_pm_loop
  
print_string_pm_done:
  popa
  ret

gdt.asm(用于设置 GDT 和 GDT 描述符,注释以便更好地理解)

; GDT
gdt_start:

gdt_null:
  dd 0x0
  dd 0x0
  
gdt_code:
  ; base=0x0, limit=0xfffff
  ; 1st flags: (present)1 (privilege)00 (descriptor type)1 -> 1001b
  ; type flags: (code)1 (conforming)0 (readable)1 (accessed)0 -> 1010b
  ; 2nd flags: (granularity)1 (32-bit default)1 (64-bit seg)0 (AVL)0 -> 1100b
  dw 0xffff     ; Limit (bits 0-15)
  dw 0x0        ; Base (bits 0-15)
  db 0x0        ; Base (bits 16-23)
  db 10011010b  ; 1st flags (4 bits) and type flags (4 bits)
  db 11001111b  ; 2nd flags (4 bits) and limit (4 bits)
  db 0x0        ; Base (bits 24-31)
  
gdt_data:
  ; Same as code segment except for the type flags:
  ; type flags: (code)0 (expand down)0 (writable)1 (accessed)0 -> 0010b
  dw 0xffff     ; Limit (bits 0-15)
  dw 0x0        ; Base (bits 0-15)
  db 0x0        ; Base (bits 16-23)
  db 10010010b  ; 1st flags (4 bits) and type flags (4 bits)
  db 11001111b  ; 2nd flags (4 bits) and limit (4 bits)
  db 0x0        ; Base (bits 24-31)
  
gdt_end:

; GDT descriptor
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

f_switch_to_pm.asm(用于切换到 32 位保护模式)

[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
  
  mov ebp, 0x90000
  mov esp, ebp
  
  call BEGIN_PM

标签: assemblyqemuboot

解决方案


推荐阅读