assembly - 为什么这个引导扇区只在 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
解决方案
推荐阅读
- apache - 启用 SSL 后 Tomcat 服务未启动 - https
- matplotlib - matplotlib 更改箭头颜色
- nlp - 如何分析使用 Spacy 训练的 NER?
- java - 如何通过“?” 在以 id 作为我的 url 的 URL android 中给出如下
- javascript - 如何在单击按钮时从数据库中一次检索 1 行?
- python - 又一个 Python 相对导入事故
- c# - Microsoft.AspNet.OData 响应缺少 OData 注释
- go - 使用 1) 自定义配置和 2) 伐木工人进行 zap 日志记录
- python - 分区相等子集和的解决方案性能(DP,哈希表)
- javascript - 如何在 React 中使用 async/await 等待数据完成提取