На втором этапе моего загрузчика я пытаюсь загрузить некоторые сектора с виртуальной дискеты в память в bochs, но после вызова int 0x13
процедура просто не возвращается.Чтение гибких дисков (AH = 0x2, int 0x13) не завершено
Я считаю, что соответствующий код из моего второго этапа:
bootsys_start:
mov %cs, %ax
mov %ax, %ds
/*
* Remap IRQs. Interrupts have been disabled in the
* bootloader already.
*/
mov i8259A_ICW1($i8259A_IC4), %al
out %al, i8259A_ICW1_ADDR($i8259A_MASTER)
out %al, i8259A_ICW1_ADDR($i8259A_SLAVE)
mov i8259A_ICW2($USER_INT_START), %al
out %al, i8259A_ICW2_ADDR($i8259A_MASTER)
mov i8259A_ICW2($USER_INT_START + 8), %al
out %al, i8259A_ICW2_ADDR($i8259A_SLAVE)
mov i8259A_ICW3($0x4), %al
out %al, i8259A_ICW3_ADDR($i8259A_MASTER)
mov i8259A_ICW3($0x2), %al
out %al, i8259A_ICW3_ADDR($i8259A_SLAVE)
mov i8259A_ICW4($i8259A_uPM & i8259A_x86), %al
out %al, i8259A_ICW4_ADDR($i8259A_MASTER)
out %al, i8259A_ICW4_ADDR($i8259A_SLAVE)
call mm_detect
/* Load the kernel now. */
xor %bp, %bp
1:
mov $KERNEL_ORG >> 0x4, %ax
mov %ax, %es
mov $KERNEL_ORG & 0xf, %bx
mov $0x200 | KERNEL_SECTORS, %ax
mov $(KERNEL_C << 0x8) | KERNEL_S, %cx
mov $(KERNEL_H << 0x8) | FLOPPY_DRV, %dx
int $0x13 /* <--- This int 0x13 doesn't seem to return */
jnc 1f
cmp $0x2, %bp
je floppy_err
inc %bp
xor %ah, %ah
int $0x13
jmp 1b
Весь код можно найти в моем Github repository. Для того, чтобы построить просто использовать make all
, а затем запустить с Bochs с помощью команды bochs
Первое, что я сделал проверки я действительно получил все параметры правильно. r
урожайности оболочки Bochs': (. Номер сектора и высокие два бита цилиндра нет)
CPU0:
rax: 00000000_534d0201 rcx: 00000000_00000005
rdx: 00000000_534d0000 rbx: 00000000_00000000
rsp: 00000000_00007700 rbp: 00000000_00000000
rsi: 00000000_000e0005 rdi: 00000000_00000316
r8 : 00000000_00000000 r9 : 00000000_00000000
r10: 00000000_00000000 r11: 00000000_00000000
r12: 00000000_00000000 r13: 00000000_00000000
r14: 00000000_00000000 r15: 00000000_00000000
rip: 00000000_00000036
eflags 0x00007046: id vip vif ac vm rf NT IOPL=3 of df if tf sf ZF af PF cf
ah = 0x2
(подпрограмма ID), al = 0x1
(количество секторов), ch = 0x0
(младший байт числа цилиндров), cl = 0x5
, dh = 0x0
(номер главы), dl = 0x0
(диск номер).
sreg
принты для es
:
es:0x0000
и bx = 0x0
, поэтому сектор загружается 0x0:0x0
, так же, как я предполагал.
Я попробовал несколько вещей:
Нагрузка на физический адрес
0x600
Я подумал, что, может быть, перекрывая IVT или BDA может не быть хорошей идеей во время выполнения BIOS прерываний , поэтому я попытался загрузить сектор в
0x600
(es = 0x60
,bx = 0x0
) (Я знаю, что размер BDA составляет всего 256 байт). Тот же результат.Загрузите первый сектор на диске
Возможно чтение пятый сектор как-то выходит за границы или что? Код, который использует
int 0x13
для чтения моего второго этапа, работает, как и ожидалось.int 0x13
на моем втором этапе подобен, поэтому я ожидал, что он сработает. В качестве теста я изменил свой второй этап, чтобы прочитать сектор 1, и он все еще не работает.обнуления верхнюю часть
eax
Я подумал, может быть действительно есть ошибка в процедуре BIOS и каким-то образом
eax
используется и неax
. Я попытался обнулить верхнюю 16-битную частьeax
... безрезультатно.
Как я уже говорил ранее, я уже загрузил некоторые сектора с диска в память.правильного содержания GPRS перед int 0x13
следующим образом (полученный с использованием r
в Bochs оболочки):
CPU0:
rax: 00000000_00000203 rcx: 00000000_00090002
rdx: 00000000_00000000 rbx: 00000000_00000000
rsp: 00000000_00007700 rbp: 00000000_00000000
rsi: 00000000_000e7cdd rdi: 00000000_000000e2
r8 : 00000000_00000000 r9 : 00000000_00000000
r10: 00000000_00000000 r11: 00000000_00000000
r12: 00000000_00000000 r13: 00000000_00000000
r14: 00000000_00000000 r15: 00000000_00000000
rip: 00000000_00007c59
eflags 0x00007046: id vip vif ac vm rf NT IOPL=3 of df if tf sf ZF af PF cf
sreg
дает es:0x8f60
, который представляет собой динамически вычисляться адрес непосредственно перед EBDA.
Сравнивая оба варианта, я не вижу существенных различий, которые могут повлиять на работу процедуры прерывания, поэтому проблема не может быть параметрами, передаваемыми через регистры.
Есть ли у кого-нибудь другие предложения о том, что делать? Я вроде потерял здесь ...
Вы пытались изолировать проблему с помощью [mcve]? В частности, как вы настраиваете регистры сегментов, учитывая, что IP-адрес равен 36h в первом случае и 7c59h во втором. –
", поэтому сектор загружается в 0x0: 0x0" - так, err, переписывая таблицу векторов прерываний? – davmac
@MargaretBloom 'cs' является' 0x8f60' для первого, '0x0' для последнего. Чтобы очистить ситуацию: BIOS загружает загрузчик на физический адрес '0x7c00', загрузчик загружает загрузчик второго уровня прямо под EBDA, начальное значение которого получается динамически, второй загрузчик загружает ядро на физический адрес' 0x0'. Я бы сделал MCVE, чтобы проверить, что загрузочные сектора работают вообще, если ** ** ** попытка была обработана. Однако загрузка вторичного загрузчика работает просто отлично. – Downvoter