我正在构建一个业余操作系统,但在某种程度上它不起作用(有一个黑屏幕没有显示任何内容),同时我试图知道为什么我试图使最小的内核不适当地工作,这反而导致了一个古鲁镇静错误,我怀疑这与int 13h有关。
这是生成古鲁冥想错误的代码:
VGA_MEMORY equ 0xB8000
org 0x7C00
bits 16
mov ax, VGA_MEMORY >> 4
mov es, ax
mov ax, 0x07E0
mov ss, ax
mov esp, 0xFFF0
mov ax, 0
mov ds, ax
; Disable the annoying cursor
mov ah, 0x01
mov ch, 001_11111b
int 0x10
reset_disk_hdd:
mov ah, 0x00 ; reset function
int 0x13 ; disk int
jc reset_disk_hdd
mov ax, 00h
mov ds, ax
mov si, disk_address_packet
read_disk_hdd:
mov ah, 42h ; read function
int 0x13 ; disk int
jc read_disk_hdd
jmp $
disk_address_packet:
db 10h ; size of DAP (set this to 10h)
db 00h ; unused, should be zero
dw 44h ; number of sectors to be read
dd 0x0000_7E00 ; segment:offset pointer to the memory buffer to which sectors will be transferred
dq 01h ; absolute number of the start of the sectors to be read
times 510-($-$$) db 0
dw 0xAA55
dw 'H'我开始使用的原始代码读取硬盘第二扇区中的一个双字,它基本上是前景的颜色,背景的颜色和屏幕上打印的字符,然后将这个双字移到0xB 8000,以便在屏幕上打印。但是当我看到这个黑屏幕什么都没有显示的时候,我开始尽可能地减少代码以保持这个错误,但是却得到了一个Guru冥想错误。例如,请注意,我正在从磁盘读取精确的44h扇区。这是一直给我错误的最低数字。
以下是我使用以下代码打开虚拟机时使用的命令:
mkdir vbox ; \
VBoxManage controlvm "X" poweroff ; \
sleep 1 ; \
VBoxManage unregistervm "e0b08add-d834-4af5-89e8-05abec11aa78" ; \
rm -r vbox/X ; \
rm kernel ; \
rm kernel.raw ; \
rm kernel.vdi ; \
VBoxManage createvm \
--name "X" \
--ostype "Other" \
--register \
--basefolder "$(pwd)/vbox" \
--uuid "e0b08add-d834-4af5-89e8-05abec11aa78" \
--default ; \
VBoxManage modifyvm "e0b08add-d834-4af5-89e8-05abec11aa78" \
--usbxhci on \
--memory 8 ; \
nasm -l kernel.lst kernel.asm ; \
dd if=/dev/zero of=kernel.raw bs=1024 count=2048 ; \
dd if=kernel of=kernel.raw conv=notrunc ; \
VBoxManage convertfromraw kernel.raw kernel.vdi --format VDI ; \
VBoxManage storageattach "X" \
--storagectl "IDE" \
--port 0 \
--device 0 \
--type hdd \
--medium "$(pwd)"/kernel.vdi ; \
VBoxManage startvm "X"; \我正在使用Virtualbox 6.1.0
这些是我的操作系统规范,为了以防万一,我添加了这些规范,因为我不知道您是否认为它有用:

我真正想知道的是,我是否遗漏了什么东西(如果是的话,是什么),还是虚拟机的实际错误。
编辑
迈克尔·佩奇评论道:
BIOS有一条规则,因为DMA (直接内存地址),所以不能越过64 for边界。我不知道virtualbox是否强制执行它,但我可以看到,如果您在(0x7e00) +(每个扇区的扇区*字节数)> 0x10000 (0x10000=64KiB)加载的地址可能会出现问题。不过,理论上,如果这是问题,我预计任何大于0x41扇区(0x42 * 512 + 0x7e00) = 0x10200都会出现潜在的问题。如果从0x1000:0x0000开始加载0x44扇区,而不是从0x0000:0x7e00开始加载0x44扇区,它会失败吗?
我更改了汇编代码,将缓冲区地址设置为0x10000,但程序仍然无法工作。然而,现在的问题是不同的:我没有得到古鲁冥想,我只得到一个黑色的屏幕,没有打印任何东西。当我只加载3 3Fh扇区时就会发生这种情况,但是当我加载3 3Fh以下的任意多个扇区时,程序将正确地输出'H‘字符:
VGA_MEMORY equ 0xB8000
GREEN equ 0x2
RED equ 0x4
org 0x7C00
bits 16
mov ax, VGA_MEMORY >> 4
mov es, ax
mov ax, 0x07E0
mov ss, ax
mov esp, 0xFFF0
mov ax, 0
mov ds, ax
; Disable the annoying cursor
mov ah, 0x01
mov ch, 001_11111b
int 0x10
reset_disk_hdd:
mov ah, 0x00 ; reset function
int 0x13 ; disk int
jc reset_disk_hdd
mov ax, 00h
mov ds, ax
mov si, disk_address_packet
read_disk_hdd:
mov ah, 42h ; read function
int 0x13 ; disk int
jc read_disk_hdd
mov ax, VGA_MEMORY >> 4
mov es, ax
mov ax, 0x1000
mov ds, ax
mov ax, [ds:0x0000]
mov [es:0x00], ax
jmp $
disk_address_packet:
db 10h ; size of DAP (set this to 10h)
db 00h ; unused, should be zero
dw 3Fh ; number of sectors to be read
dd 0x1000_0000 ; segment:offset pointer to the memory buffer to which sectors will be transferred
dq 01h ; absolute number of the start of the sectors to be read
times 510-($-$$) db 0
dw 0xAA55
dw (RED << 4 | GREEN) << 8 | 'H'https://stackoverflow.com/questions/60684445
复制相似问题