【问题标题】:Having Trouble Saving Boot Sector On Disk And OS On Disk Then Loading It In Memory无法在磁盘上保存引导扇区和在磁盘上保存操作系统,然后将其加载到内存中
【发布时间】:2013-04-28 23:54:49
【问题描述】:

背景资料

我正在开发一个类似 OS 的简单 DOS。所以我不打算很快进入保护模式。操作系统将以汇编语言编写;顺便说一句,NASM 语法。引导扇区应该将引导扇区保存在硬盘的第一个扇区,并将操作系统代码保存在第二个扇区。这样它就可以从硬盘启动,而不是从 CD 映像启动。

问题

问题是引导扇区似乎将所有内容正确保存在硬盘上。但是当我重新启动 VMware Player 并弹出虚拟 CD-ROM 时。它引导背景为绿色(图 1.1)。这只能意味着引导扇区没有加载地址 0x7e00 处的第二个扇区,并且无法跳转。奇怪的是没有设置进位标志,所以我 我假设没有发生错误。所以基本上当我从 CD-ROM 映像启动时,它会显示一切正常,如图 1.2 所示。但是当我重新启动并从硬盘启动时,它无法跳转到应该在 0x7e00 加载的操作系统。引导扇区在 0x7c00 加载。我假设我的段地址是正确的,也许我的偏移地址不正确,或者我的磁盘读写完全错误?

操作系统成功完成的事情

  • 软件中断形式的基本系统调用。修改了IVT(中断向量表)

  • 在主硬盘上加载引导扇区,BIOS可以将引导扇区从硬盘加载到内存位置0x7c00

可能导致问题的代码

这是 boot.asm 代码:​​

[ORG 0x7c00] ; BIOS loads at 0x7c00 in memory

jmp start

%include "C:\Users\OSDEV\OS-SRC\MonsterOS\source\syscalls\syscalls.inc"

start:

xor ax, ax ; make it zero
mov ds, ax ; Data segment is zero

;Set desired video mode (Graphics Mode)
mov ah, 0
mov al, 12h
int 10h

call init_int

;Set desired background color (Green)
mov ah, 0x0b 
mov bh, 0
mov bl, 2
int 10h 

; Display Box Shaped Cursor

mov ch, 0
mov cl, 7
mov ah, 1
int 10h


;Save BootLoader on the DISK


xor ax, ax
mov es, ax    ; ES <- 0
mov cx, 1    ; cylinder 0, sector 1
mov dx, 0080h ; DH = 0 (head), drive = 80h (0th hard disk)
mov bx, 7c00h ; segment offset of the buffer
mov ax, 0301h ; AH = 03 (disk write), AL = 01 (number of sectors to write)
int 13h

;Save OS on the DISK


xor ax, ax
mov es, ax    ; ES <- 0
mov cx, 2     ; cylinder 0, sector 2
mov dx, 0080h ; DH = 0 (head), drive = 80h (0th hard disk)
mov bx, 7e00h ; segment offset of the buffer
mov ax, 0301h ; AH = 03 (disk write), AL = 01 (number of sectors to write)
int 13h

;Load OS from DISK at 0x7e00

xor ax, ax
mov es, ax    ; ES <- 0
mov cx, 2     ; cylinder 0, sector 2
mov dx, 0080h ; DH = 0 (head), drive = 80h (0th hard disk)
mov bx, 7e00h ; segment offset of the buffer
mov ax, 0201h ; AH = 02 (disk read), AL = 01 (number of sectors to read)
int 13h
jc err


jmp 0h:0x7e00 ; Jump To OS

err:

mov ax, err_msg
mov bh, 0
mov bl, 0xf
int 21h ; Print error message

err_msg: db 'Error Failed To Load OS From Disk!', 0

times 510-($-$$) db 0
   db 0x55
   db 0xAA

这是 os.asm:

[ORG 0x7e00]



xor ax, ax ; make it zero
mov ds, ax ; Data segment is zero
mov es, ax



; Clear Screen

int 27h

;Set desired background color (Green)
mov ah, 0x0b 
mov bh, 0
mov bl, 2
int 0x10    

; Display Box Shaped Cursor

mov cx, 0607h 
mov ah, 1
int 10h

; Print Desired Message

mov ax, msg
mov bh, 0
mov bl, 0xf
int 21h


int 23h ; Print newline



hang:

    mov ax, buffer
    int 25h ; SIZE(buffer)

    mov ax, buffer
    int 24h ;ZERO(buffer)

    ; Print Desired Message

    mov ax, cli_msg
    mov bh, 0
    mov bl, 0xf

    int 21h ; print ax=msg bl=blue

    ; Get Input
    mov bx, buffer
    int 22h ; Read From Keyboard And Print The String With Line Feed

    ; ECHO String Stored At The Address Buffer

    mov ax, buffer
    mov bh, 0
    mov bl, 0xf
    int 21h ; 

    int 23h ; Print newline

    jmp hang

msg: db 'Welcome To MonsterOS!', 0
cli_msg: db 'MonsterOS> ', 0
buffer: times 64 db 0

这里是脚本 build.bat 代码:

nasm -f bin C:\Users\OSDEV\OS-SRC\MonsterOS\source\boot.asm -o C:\Users\OSDEV\OS-SRC\MonsterOS\bin\boot.bin 
nasm -f bin C:\Users\OSDEV\OS-SRC\MonsterOS\source\os.asm -o C:\Users\OSDEV\OS-SRC\MonsterOS\bin\os.bin 
copy /b C:\Users\OSDEV\OS-SRC\MonsterOS\bin\boot.bin + C:\Users\OSDEV\OS-SRC\MonsterOS\bin\os.bin C:\Users\OSDEV\OS-SRC\MonsterOS\bin\img.bin
miso C:\Users\OSDEV\OS-SRC\MonsterOS\bin\os.iso -ab C:\Users\OSDEV\OS-SRC\MonsterOS\bin\img.bin

后期脚本

中断 21h、22h、23h、24h、25h、26h 是我为我的操作系统编写的自定义软件中断。如果您还有任何问题或需要更多代码或信息,我在这里提供更多信息。

解决方案

对于那些关心的人,我通过在 VirtualBox 创建并从 VHD 引导的 VHD 中编写 img.bin 来解决它。所以它就像一个魅力。顺便说一句,我使用了十六进制编辑器。

图 1.1

图 1.2

【问题讨论】:

  • 不清楚 0x7E00 处的“操作系统”来自何处。 BIOS 将引导扇区加载到 0x7C00,然后将其写入硬盘(在引导扇区中这样做很奇怪)。然后你将 0x7E00 写入硬盘并读回它......但是首先如何到达 0x7E00?
  • 好吧,我没有显示整个代码,这可能是您感到困惑的原因。那么你可能是对的。我在我的问题中发布了更多代码。
  • @FrankKotler 好吧,我想从硬盘启动,而不是从 CD 映像启动。我是操作系统开发的新手,如果我做的不对,请原谅。 :D

标签: assembly x86 bootloader osdev


【解决方案1】:

好的,请原谅。没有人天生就知道这些东西!

回到它工作的时候(你的图 1.2),你“必须”从你的 CD 映像读取扇区 2 到 0x7E00 - 类似于你在引导扇区结束时所做的,只是从不同的驱动器(@987654321 @)。我猜 BIOS 认为 CD 映像是驱动器 0。引导驱动器号应该在 dl 中,因此您可以不理会它(尽管将其设为 dh 0)。完成此操作后,您可能可以从 0x7C00 写入硬盘驱动器(驱动器 80h)扇区 1 并从 0x7E00 写入驱动器 80h 扇区 2 - 正如您正在做的那样。但是您真的想在每次启动时都这样做吗?

在将 boot.bin 和 os.bin 复制到 img.bin 之后,我要做的是将 img.bin 写入硬盘驱动器,使用... John Fine 的 partcopy,如果你能找到的话,或者 rawwrite ,或dd 的端口(Unix 实用程序)。或者你可以用 DEBUG 来做。或者为自己编写一个小程序来做到这一点并不难。然后你应该可以从硬盘启动,完全跳过 iso 和 CD 映像。

BIOS 将扇区 1 加载到 0x7C00,但之后由您的引导代码将扇区 2 加载到 0x7E00 并跳转到它...或将其写入硬盘驱动器,读回并跳转到它,但似乎每次开机都这样做是没有意义的。

随着操作系统的发展,它会占用多个扇区,因此您需要读取多个扇区。如果您的代码正在运行,但在您添加更多功能时崩溃,这可能就是正在发生的事情。轻松修复 - 只需注意 os.bin 的大小,如果/当超过 512 字节时读取更多扇区。

次要问题:如果您的错误消息被打印出来,那么您将“失败”以尝试执行该消息并继续“进入树林”。打印后放置hang: jmp hang 以捕获它。您没有收到错误(携带标志),因为您的代码很高兴将 0x7E00 写入磁盘并将其读回,即使那里没有“代码”。我认为这就是正在发生的事情......

需要注意的一点:Bios 始终认为它启动的硬盘是“驱动器 80h”。如果您从其他驱动器启动,您想要写入引导扇区和操作系统的驱动器可能是驱动器 81h 或 82h 或 ???。小心!

【讨论】:

  • 感谢它对我帮助很大。顺便说一句,我在 Windows 8 上执行此操作,并且由于我的机器是 64 位机器,因此我的机器无法运行 PartCopy。你推荐什么替代方案。我会把你的标记为答案。
  • 我既没有运行 Windows 也没有运行 64 位,所以我不知道 PartCopy 的好选择。也许有适用于 64 位 Windows 的 RawWrite 版本?如果所有其他方法都失败了,那么您那里的代码将“几乎”做到这一点。添加代码以首先从 CD 映像读取并写入硬盘驱动器?然后扔掉这个“自定义”引导扇区并编写一个“常规”引导扇区?我认为最好找到可以在 Win64 上运行的东西?
  • 我使用了一个十六进制编辑器并将 img.bin 复制到一个 VHD 中,它就像一个魅力。所以只是想让你知道一切正常。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-13
  • 1970-01-01
  • 2020-09-21
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 2012-11-02
相关资源
最近更新 更多