Reputation: 2001
I am building a hobby operating system, but at some point it didn't work (Got a black screen not showing anything), and while trying to know why I tried to make the smallest kernel possible that worked inappropriately, which led instead to a guru medidation error, which I suspect have something to do with int 13h
This is the code that produces guru meditation error:
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'
The original code I started working with read a double word located in the second sector of the hard disk, which was basically a color for the foreground, a color for the background and a character to print in screen, and then moved that double word to 0xB8000 to have it printed on the screen. But when I got this black screen showing nothing I started to reduce the code as much as possible to keep getting this error, but instead got a Guru Meditation error. Notice, for instance, that I am reading exactly 44h sectors from disk. This is the lowest number that keep giving me the error.
Those are the commands I use to turn on the virtual machine with this code:
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"; \
I am using Virtualbox 6.1.0
These are my operating system specs, which I add just in case because I don't know if you might find it useful:
What I really want to know is whether I am missing something (and if so, what) or it's an actual bug of the virtual machine.
Michael Petch commented:
There is a rule for BIOS that you should never cross a 64KiB boundary because of DMA (direct memory address). I don't know if virtualbox enforces it but I could see that if the address you load at (0x7e00) + (the number of sectors * bytes per sector)> 0x10000 (0x10000=64KiB) a problem may occur . In theory though if that were the problem I'd expect potential problems to be with anything > 0x41 sectors (0x42 * 512 + 0x7e00) = 0x10200. If you load 0x44 sectors starting at 0x1000:0x0000 rather than 0x0000:0x7e00 does it fail?
I changed the assembly code to set the buffer address at 0x10000, but the program still doesn't work. However, the problem now is different: instead of getting a guru meditation, I only get a black screen not printing anything. This happens when I load as little as 3Fh sectors, but when I load any number of sectors below 3Fh the program correctly prints the 'H' character:
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'
Upvotes: 1
Views: 399
Reputation: 2001
To make sure int 13h ah=02h or ah=42h works as it should check the following:
Upvotes: 3