Bootloader/kernel загружается только на виртуальной машине

Итак, последние несколько недель я пытался написать начальный загрузчик и ядро ​​в сборке (x86/x86_64), и, хотя я пробовал более сложные решения, перед тем, как сам писать, я решил опробовать некоторый код, который пользователь по имени Sinned разместил здесь. Мой код загрузчика:

[BITS 16]
[ORG 0x7C00]

MOV DL, 0x0 ;drive 0 = floppy 1
MOV DH, 0x0 ;head (0=base)
MOV CH, 0x0 ;track/cylinder
MOV CL, 0x02 ;sector (1=bootloader, apparently sectors starts counting at 1 instead of 0)
MOV BX, 0x1000 ;place in RAM for kernel - I suppose randomly chosen on examples
MOV ES, BX ;place BX in pointer ES
MOV BX, 0x0 ;back to zero - also has something to do with RAM position

ReadFloppy:
MOV AH, 0x02
MOV AL, 0x01
INT 0x13
JC ReadFloppy ;if it went wrong, try again

;pointers to RAM position (0x1000)
MOV AX, 0x1000
MOV DS, AX
MOV ES, AX
MOV FS, AX
MOV GS, AX
MOV SS, AX

JMP 0x1000:0x0

;assuming we get never back here again, so no further coding needed (kernel handles everything now)

TIMES 510 - ($ - $$) db 0 ;fill resting bytes with zero
DW 0xAA55 ;end of bootloader (2 bytes)

Мой файл ядра:

;set print-registers
MOV AH, 0x0E ;function nr
MOV BH, 0x00 ;page
MOV BL, 0x07 ;color

MOV SI, msg ;move msg to SI-pointer
CALL PrintString ;call function to print SI (msg)

JMP $ ;hang

PrintString:
.next_char:
MOV AL, [SI] ;current character
OR AL, AL
JZ .print_done ;if current char is zero, go to end
INT 0x10 ;print character
INC SI ;increase pointer to msg (next character)
JMP .next_char
.exit_char
RET

msg db 'Hello world from the kernel!', 13, 10, 0

TIMES 512 - ($ - $$) db 0 ;fill the rest

Я могу получить все, чтобы хорошо собрать, и один двоичный файл создается загружается внутри VirtualBox при подключении к контроллеру гибких дисков. Хотя это дает мне уверенность в работе над моим собственным загрузчиком и ядром, я бы хотел получить удовольствие от загрузки его на голом металле.

Я попытался загрузить образ с USB-накопителей безрезультатно, и я уверен, что правильно отображаю USB-накопители. Я начинаю чувствовать, что мне здесь не хватает чего-то действительно очевидного. Я подозреваю, что это связано с использованием 13h для чтения с "дискеты", где я на самом деле пытаюсь прочитать необработанный двоичный файл с USB. Это тот случай? Если так, как я могу переписать загрузчик для чтения с неспецифического диска вместо дискеты?

1 ответ

Решение

Я написал несколько советов по общему загрузчику, которые применимы к этому коду. В частности, у меня есть этот совет:

  1. Когда BIOS переходит к вашему коду, вы не можете полагаться на регистры CS,DS,ES,SS,SP, имеющие действительные или ожидаемые значения. Они должны быть настроены соответствующим образом при запуске вашего загрузчика. Вы можете только гарантировать, что ваш загрузчик будет загружен и запущен с физического адреса 0x00007c00 и что номер загрузочного диска загружен в регистр DL.

Загрузочный диск первой дискеты обычно равен 0, поэтому ваша виртуальная машина, вероятно, работала, потому что вы загрузили образ дискеты, смонтированный как виртуальный диск A: . Код, который вызывает у вас проблемы, находится в вашем ReadFloppy код. В частности эта строка:

MOV DL, 0x0 ;drive 0 = floppy 1

Вы жестко программируете ноль, где вы должны использовать значение, переданное BIOS. В любой системе, где вы загрузились как что-либо, кроме дисковода А: он, скорее всего, потерпит неудачу. Чтобы решить проблему, просто удалите строку выше.

Я рекомендую ознакомиться с другими советами по загрузке, приведенными в приведенной ссылке.

Другие вопросы по тегам