Почему я получаю эту медитацию Гуру, используя int 13h? - PullRequest
1 голос
/ 14 марта 2020

Я собираю операционную систему для хобби, но в какой-то момент она не сработала (черный экран ничего не показывает), и, пытаясь понять, почему я попытался сделать наименьшее возможное ядро, которое работало бы неправильно, что привело к вместо ошибки медитации гуру, которая, я подозреваю, как-то связана с 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'

1 Ответ

3 голосов
/ 15 марта 2020

Чтобы убедиться, что int 13h, ah = 02h или ah = 42h, работает следующим образом:

  • Где бы вы ни загружали байты с диска в память, убедитесь, что они не перекрывают стек
  • Не загружайте более 0x7f секторов, так как некоторые старые BIOS не поддерживают чтение нескольких секторов> = 0x80
  • Буфер не должен пересекать границу 64 КБ
  • Вы не касаетесь таблицы векторов прерываний, BDA, EBDA, B IOS или любой другой области памяти, запрещенной или не свободной для использования. См. Карта памяти и Верхняя карта памяти .
...