Я собираю операционную систему для хобби, но в какой-то момент она не сработала (черный экран ничего не показывает), и, пытаясь понять, почему я попытался сделать наименьшее возможное ядро, которое работало бы неправильно, что привело к вместо ошибки медитации гуру, которая, я подозреваю, как-то связана с 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'
Исходный код, с которым я начал работать, читал двойное слово, расположенное во втором секторе жесткого диска, которое в основном представляло собой цвет для переднего плана, цвет для фона и символ для печати на экране, а затем переместило это двойное слово в 0xB8000, чтобы оно было напечатано на экране. , Но когда я получил этот черный экран, на котором ничего не показывалось, я начал максимально сокращать код, чтобы продолжать получать эту ошибку, но вместо этого получил ошибку медитации Гуру. Обратите внимание, например, что я читаю с диска ровно 44 ч. Сектора. Это наименьшее число, которое продолжает давать мне ошибку.
Это команды, которые я использую для включения виртуальной машины с этим кодом:
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
Это мои спецификации операционной системы, которые я добавляю на всякий случай, потому что я не знаю, можете ли вы найти это полезным:
Что я действительно хочу знать, так это то, я что-то упустил (и если да, то что) или это реальная ошибка виртуальной машины.
РЕДАКТИРОВАТЬ
Майкл Петч прокомментировал:
Есть правило для B IOS вы никогда не должны пересекать границу 64 КБ из-за DMA (прямого адреса памяти). Я не знаю, применяет ли это виртуальная коробка, но я вижу, что если адрес, который вы загружаете в (0x7e00) + (число секторов * байт на сектор)> 0x10000 (0x10000 = 64 КБ), может возникнуть проблема. Теоретически, если бы это была проблема, я бы ожидал, что потенциальные проблемы будут с чем-то> 0x41 секторов (0x42 * 512 + 0x7e00) = 0x10200. Если вы загружаете 0x44 секторов, начиная с 0x1000: 0x0000, а не 0x0000: 0x7e00, это не получается?
Я изменил код сборки, чтобы установить адрес буфера на 0x10000, но программа по-прежнему не работает. Однако теперь проблема в другом: вместо медитации гуру я получаю только черный экран, ничего не печатая. Это происходит, когда я загружаю всего 3Fh сектора, но когда я загружаю любое количество секторов ниже 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'