Простой загрузчик не может читать секторы с int 13h на реальной машине
У меня странная проблема с моим простым кодом загрузчика.
Он должен считывать сектор с диска через функцию прерывания BIOS 13h 02h в видеопамять в текстовом режиме (просто чтобы посмотреть, работает ли он). Он отлично работает на эмуляторах (Bochs, QEmu), но когда я пытаюсь загрузить его с Pendrive, подключенного к реальной машине (Acer Extensa 5620Z), он просто очищает экран и печатает:
PCI System Error on Bus/Device/Function 0000h
PCI System Error on Bus/Device/Function 0200h
и это не похоже на загрузку каких-либо данных. После вызова этого прерывания не установлен флаг переноса и нет кода ошибки в AH, только 1 (предположительно, число прочитанных секторов).
Вот соответствующая часть кода:
mov bootdev, %dl # Device we're booting from.
# ES=B800 (video memory segment in mode 03h)
mov $0xB800, %ax
mov %ax, %es
# Read one block.
mov $0x0001, %cx # C:0, S;1
mov $0x00, %dh # H:0
xor %bx, %bx # ES:BX = B800:0000 = output buffer.
mov $0x0201, %ax # Function 02h: read sectors (just one).
stc
int $0x13 # Disk controller BIOS interrupt.
jc error # On error, print an error message.
Номер устройства, с которого мы загружаемся, взят из самого BIOS (в DL
) и хранится в bootdev
для последующего использования. Кажется, с этим номером все в порядке, я могу вызвать функцию 08h прерывания 13h, чтобы получить из него правильную геометрию привода. Просто когда я пытаюсь загрузить любые сектора с помощью функции 02h, появляется это сообщение об ошибке.
Есть идеи, что может быть не так?
1 ответ
Есть две вещи, которые отличаются на "реальной" машине по сравнению с виртуальной машиной:
Во-первых: дисководы гибких дисков могут иногда выходить из строя до тех пор, пока они действительно не прочитают данные из-за механических задержек, которые имеют настоящие дисководы гибких дисков, в то время как моделируемые не имеют задержек. Поскольку вы загружаетесь с USB, это не может быть причиной.
Второе: компоненты памяти не эмулируются, а реальны. Вы не можете быть уверены, что память на адресе B800:0 ведет себя как "обычная" оперативная память на реальной машине. B800:0 - это не "обычная" ОЗУ, а графическая ОЗУ, которая может вести себя не так, как обычная. Попробуйте вместо этого прочитать по адресу 9000:0, а затем скопировать данные в B800:0 с помощью "REP MOVSW".