汇编语言 - 读取虚拟磁盘的下一个扇区

4
作为世界上任何一位程序员至少有一次尝试创建自己的“革命性”的新操作系统,我也在努力中 :D。
好吧,我正在使用虚拟模拟器(Oracle VM Virtual Box),其中我创建了一个新的未知操作系统,并使用vmdk磁盘。我喜欢vmdk文件,因为它们只是普通文件,所以我可以将我的引导加载程序粘贴到虚拟硬盘的前512个字节上。
现在,我正在尝试读取这个虚拟磁盘的下一个扇区,在该扇区上我会放置一个简单的内核来显示一条消息。
我有两个问题:
  • Am I reading the second segment (the first -512 bytes- is occupied by the bootloader) correctly? CODE:

    ReadDisk:
        mov bx, 0x8000  ; segment
        mov es, bx
        mov bx, 0x0000  ; offset
    
        mov ah, 0x02  ; read function
        mov al, 0x01  ; sectors - this might be wrong, trying to read from hd
        mov ch, 0x00  ; cylinder
        mov cl, 0x02  ; sector
        mov dh, 0x00  ; head
        mov dl, 0x80  ; drive - trying to read from hd
        int 0x13   ; disk int
        jc ReadDisk
        jmp [es:bx]   ; buffer
    

    Here, I get the error message, after checking CF. However, if I use INT 13, 1 to get last status message, AL is 0 - so no error is saved.

  • Am I pasting my simple kernel in the correct place inside the vmdk? What I do is pasting it after the 512th byte of the file, the first 512 bytes, as I said, are the boot-loader. The file would look like this:

    BE 45 7C E8 16 00 EB FE B4 0E B7 00 B3 07 CD 10 <- First sector
    C3 AC 08 C0 74 05 E8 EF FF EB F6 C3 B4 00 B2 80
    CD 13 BE 5D 7C 72 F5 BB 00 80 8E C3 BB 00 00 B4 
    02 B0 06 B5 00 B1 01 B6 00 B2 07 CD 13 BE 4E 7C 
    72 CF 26 FF 27 57 65 6C 63 6F 6D 65 21 00 52 65 
    61 64 69 6E 67 20 65 72 72 6F 72 21 00 52 65 73 
    65 74 74 69 6E 67 20 65 72 72 6F 72 21 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA <- Boot-loader signature
    B4 0E B0 2E CD 10 EB FE 00 00 00 00 00 00 00 00 <- Start of the second sector
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    

所以,我正在尝试将内核添加到第二个扇区的方式是这样的。你认为这有什么问题吗?谢谢!

更新

好的,现在我没有收到任何错误,但我没有看到加载的代码被执行。它应该在窗口上显示一个点:

;--------------------------------------------
; 'load.asm'
; loaded from 'boot.asm'

[org 0x8000]
[bits 16]

;--------------------------------------------

main:
mov ah, 0x0E  ; print function
mov al, '.'   ; ascii char
int 0x10   ; IO int

jmp $    ; hang

你真的应该去http://osdev.org/并在那里提问。还要阅读一些来自其维基的文章。 - Griwes
然而,如果我使用INT 13,1来获取最后的状态消息,AL为0-因此没有错误被保存。实际上,状态是在ah中返回的,而不是al。请参考https://github.com/cirosantilli/ralf-brown-interrupt-list/blob/master/inter61a/INTERRUP.B#L1591--此外,当操作返回时带有CY(进位标志设置)时,所有操作都会在`ah`中返回状态,您无需显式调用01h函数。 - ecm
2个回答

6

一个问题在这里:

jmp [es:bx]

这将从寄存器 es(段部分)和 bx(偏移部分)所包含的地址中读取一个16位偏移量,然后将ip设置为该16位偏移量。

您可能想使用以下内容:

jmp some_constant1:some_constant2

这将把cs设置为some_constant1,将ip设置为some_constant2。毫不意外,这两个常量的好选择分别是0x8000和0,因为这是您的代码加载的位置。
现在,第二个问题出现了:
[org 0x8000]

这个 org 告诉 NASM 以这种方式生成代码,使得如果在偏移量为 0x8000 的位置加载,它将能够正常工作。现在,偏移量 0x8000 并不等同于段地址 0x8000。如果你使用 jmp 0x8000:0,那么你也应该使用:

[org 0]

1

如果失败了,请再试一次。我认为当磁盘开始旋转时,你会收到一个没有消息的错误提示,所以模拟器可能会故意在第一次失败。在bochs和qemu中,我尝试了四次都很成功,但我没有在其他设备上尝试过。在读取之前,您可能还需要重置驱动器控制器以清除任何先前的错误。使用中断0x13和al清除以及dl中的驱动器编号。


注意:硬编码驱动器号码可能暂时有效,但无法支持从其他驱动器启动。BIOS 在启动引导加载程序时应该将驱动器号码保留在 dl 中,以便您可以保存它。

我仍然无法得到我想要的。没有显示错误,但是加载到内存中的代码没有被执行。请查看更新! - ali
bhbl也会影响打印函数的结果。个人建议使用中断0x10功能0来设置视频模式,并直接写入视频内存。另外,如果使用0x8000作为段地址,线性地址应为0x80000,因此org指令是错误的。对于该程序,只有在该位置的RAM不存在时才会出现问题。如果可以的话,您应该连接调试器并确保处理器跳转到正确的位置。 - ughoavgfhw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接