在我的引导加载程序的第二阶段,我试图将虚拟软盘上的一些扇区加载到bochs的内存中,但是在调用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 存储库中找到。要构建,只需使用BOCHSmake all
,然后使用命令运行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
我认为在执行 BIOS 中断例程期间覆盖 IVT 或 BDA 可能不是一个好主意,所以我尝试将扇区加载到
0x600
(es = 0x60
,bx = 0x0
) (我知道 BDA 的大小只有 256 字节)。结果相同。加载磁盘上的第一个扇区
也许阅读第五个部门以某种方式越界或其他什么?用于读取我的第二阶段的代码
int 0x13
按预期工作。在int 0x13
我的第二阶段是相似的,所以我希望它能够工作。作为测试,我将第二阶段更改为读取扇区 1,但仍然无法正常工作。将上半部分归零
eax
我想也许 BIOS 例程中确实存在一个错误,并且以某种方式
eax
使用而不是ax
。我尝试将 ... 的高 16 位部分归零,eax
但无济于事。
正如我之前所说,我已经将一些扇区从磁盘加载到内存中。之前的 GPR 的内容int 0x13
如下(r
在 bochs shell 中获得):
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
yield es:0x8f60
,它是 EBDA 之前的动态计算地址。
比较两者,我没有看到可能影响中断例程功能的显着差异,因此问题不在于通过寄存器传递的参数。
有人对该怎么做有其他建议吗?