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存储库中找到。要构建,请使用
make all
,然后使用命令bochs
在BOCHS上运行。
我首先要做的是确认我是否真正正确地获得了所有参数。在bochs的shell中,r
会产生以下结果:
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
我认为在执行BIOS中断例程期间覆盖IVT或BDA可能不是一个好主意,所以我尝试将扇区加载到
0x600
(es = 0x60
,bx = 0x0
)(我知道BDA只有256字节大小)。结果相同。加载磁盘上的第一个扇区
也许读取第五个扇区超出了边界或其他什么问题?使用
int 0x13
读取我的第二阶段的代码按预期工作。我的第二阶段中的int 0x13
类似,因此我希望它能够工作。作为测试,我修改了我的第二阶段以读取扇区1,但仍然不起作用。清零
eax
的高位部分我想也许BIOS例程确实存在错误,某种方式使用了
eax
而不是ax
。我尝试清零eax
的高16位部分...但没有效果。
正如我之前所说,我已经将一些扇区从磁盘加载到内存中。在int 0x13
之前,GPRs的内容如下(使用bochs shell中的r
获得):
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 前动态计算出来的地址。
比较两者,我没有看到任何可能影响中断例程功能的显著差异,因此问题不可能是通过寄存器传递的参数。
有人有其他建议吗?
0x0
到0x9fc00
,后者等于 EBDA 起始地址。该条目类型为0x1
,表示可供操作系统使用的内存。我正在加载三个扇区,如我对0x8f600
的回答所述,远低于 EBDA。该区域必须空闲以供使用。 - cadaniluk