【问题标题】:My operating system doesn't boot in VMWare我的操作系统无法在 VMWare 中启动
【发布时间】:2016-01-08 14:30:58
【问题描述】:

我正在制作一个名为 TriangleOS 的操作系统,其中包含一些文件,如 sysldr.syskernel.sys 等。当我在 VMWare 上运行它时,我收到了这个错误:

移除磁盘或其他媒体。按任意键重启

我正在 Windows 10 上编译。我正在使用 partcopy 创建我的引导扇区。我输入了:

partcopy.exe boot.asm 0 200 -f0

这是我的文件boot.asm的内容:

bits    16
org     0
%include"Floppy16.inc"

start:  jmp main
Print:
lodsb       
or  al, al  
jz  PrintDone
mov ah, 0eh 
int 10h
jmp Print   
PrintDone:
ret
main:  
cli                     
mov     ax, 0x07C0      
mov     ds, ax
mov     es, ax
mov     fs, ax
mov     gs, ax
mov     ax, 0x0000      
mov     ss, ax
mov     sp, 0xFFFF
sti                     
mov     si, msgLoading
call    Print
LOAD_ROOT:
xor     cx, cx
xor     dx, dx
mov     ax, 0x0020                        
mul     WORD [bpbRootEntries]             
div     WORD [bpbBytesPerSector]          
xchg    ax, cx
mov     al, BYTE [bpbNumberOfFATs]        
mul     WORD [bpbSectorsPerFAT]           
add     ax, WORD [bpbReservedSectors]     
mov     WORD [datasector], ax             
add     WORD [datasector], cx
mov     bx, 0x0200                        
call    ReadSectors
mov     cx, WORD [bpbRootEntries]         
mov     di, 0x0200                        
.LOOP:
    push    cx
    mov     cx, 0x000B                    
    mov     si, ImageName                 
    push    di
    rep  cmpsb                            
    pop     di
    je      LOAD_FAT
    pop     cx
    add     di, 0x0020                    
    loop    .LOOP
    jmp     FAILURE
LOAD_FAT:
mov     dx, WORD [di + 0x001A]
mov     WORD [cluster], dx                
xor     ax, ax
mov     al, BYTE [bpbNumberOfFATs]        
mul     WORD [bpbSectorsPerFAT]           
mov     cx, ax
mov     ax, WORD [bpbReservedSectors]     
mov     bx, 0x0200                        
call    ReadSectors
mov     ax, 0x0050
mov     es, ax                            
mov     bx, 0x0000                        
push    bx
LOAD_IMAGE:
mov     ax, WORD [cluster]                
pop     bx                                
call    ClusterLBA                        
xor     cx, cx
mov     cl, BYTE [bpbSectorsPerCluster]   
call    ReadSectors
push    bx
mov     ax, WORD [cluster]                
mov     cx, ax                            
mov     dx, ax                            
shr     dx, 0x0001                        
add     cx, dx                            
mov     bx, 0x0200                        
add     bx, cx                            
mov     dx, WORD [bx]                     
test    ax, 0x0001
jnz     .ODD_CLUSTER 
.EVEN_CLUSTER:
    and     dx, 0000111111111111b         
    jmp     .DONE 
.ODD_CLUSTER:
    shr     dx, 0x0004                    
.DONE:
    mov     WORD [cluster], dx            
    cmp     dx, 0x0FF0                    
    jb      LOAD_IMAGE   
DONE:
     mov     si, msgCRLF
     call    Print
     push    WORD 0x0050
     push    WORD 0x0000
     retf
FAILURE:
mov     si, msgFailure
call    Print
mov     ah, 0x00
int     0x16          
int     0x19          
bootdevice  db 0
ImageName:   db "KRNLDR  SYS"
msgLoading:  db 0x0D, 0x0A, "Reading Kernel Loader", 0x00
msgCRLF:     db 0x0D, 0x0A, 0x00
msgProgress: db ".", 0x00
msgFailure:  db 0x0D, 0x0A, "Can't find Kernel Loader (krnldr.sys). Press Any Key to Reboot", 0x0D, 0x0A, 0x00
TIMES 510-($-$$) DB 0
DW 0xAA55

文件Floppy16.inc 是一个文件驱动助手。代码如下:

%ifndef __FLOPPY16_INC_
%define __FLOPPY16_INC_
bits    16
bpbOEM          db "TriangOS"
bpbBytesPerSector:      DW 512
bpbSectorsPerCluster:   DB 1
bpbReservedSectors:     DW 1
bpbNumberOfFATs:    DB 2
bpbRootEntries:     DW 224
bpbTotalSectors:    DW 2880
bpbMedia:       DB 0xf0
bpbSectorsPerFAT:   DW 9
bpbSectorsPerTrack:     DW 18
bpbHeadsPerCylinder:    DW 2
bpbHiddenSectors:   DD 0
bpbTotalSectorsBig:     DD 0
bsDriveNumber:          DB 0
bsUnused:       DB 0
bsExtBootSignature:     DB 0x29
bsSerialNumber:         DD 0xa0a1a2a3
bsVolumeLabel:          DB "TOS FLOPPY "
bsFileSystem:           DB "FAT12   "
datasector  dw 0x0000
cluster     dw 0x0000
absoluteSector db 0x00
absoluteHead   db 0x00
absoluteTrack  db 0x00
ClusterLBA:
    sub     ax, 0x0002
    xor     cx, cx
    mov     cl, BYTE [bpbSectorsPerCluster]
    mul     cx
    add     ax, WORD [datasector]
    ret
LBACHS:
    xor     dx, dx                    
    div     WORD [bpbSectorsPerTrack] 
    inc     dl                        
    mov     BYTE [absoluteSector], dl
    xor     dx, dx                    
    div     WORD [bpbHeadsPerCylinder]
    mov     BYTE [absoluteHead], dl
    mov     BYTE [absoluteTrack], al
    ret
; CX=>Kolko sektori da procita
; AX=>Pocetni sektor
; ES:EBX=>Na koju mem. lokaciju da ga stavi
ReadSectors:
     .MAIN
          mov     di, 0x0005                  
     .SECTORLOOP
          push    ax
          push    bx
          push    cx
          call    LBACHS
          mov     ah, 0x02                    
          mov     al, 0x01                    
          mov     ch, BYTE [absoluteTrack]    
          mov     cl, BYTE [absoluteSector]   
          mov     dh, BYTE [absoluteHead]     
          mov     dl, BYTE [bsDriveNumber]
          int     0x13                        
          jnc     .SUCCESS                    
          xor     ax, ax                      
          int     0x13                        
          dec     di                          
          pop     cx
          pop     bx
          pop     ax
          jnz     .SECTORLOOP                 
          int     0x18
     .SUCCESS
          pop     cx
          pop     bx
          pop     ax
          add     bx, WORD [bpbBytesPerSector]
          inc     ax                          
          loop    .MAIN                       
          ret

%endif

我使用这个命令编译了引导扇区:

nasm.exe -f bin boot.asm -o boot.bin

这个项目真的很大。我这样做是为了不需要 GRUB。我注意到我的十六进制编辑器在末尾55。反转正常吗?在我的代码中有正常的0xAA55。为什么它输出Remove disks or other media? 我该如何解决这个问题?有什么建议吗?

【问题讨论】:

  • 学习使用调试器并注释您的代码,尤其是在您希望其他人提供帮助时。
  • 请提供 floppy16.inc,以便您拥有一个最小完整的可验证示例。
  • partcopy.exe boot.asm 0 200 -f0 。我对partcopy一无所知,但这看起来不对。您正在将源代码复制到软盘上??! partcopy.exe boot.bin 0 200 -f0 怎么样?我的猜测是你得到的错误意味着它在你的虚拟机上找不到任何可启动媒体,它要求你插入一些东西。如果您确实将 boot.asm 复制到虚拟软盘而不是 boot.bin 上,那么我可以看到是这种情况。
  • 不相关但仍然...不要在 odd 地址初始化您的堆栈指针!最好使用even地址mov sp, 0xFFFE
  • 我非常感谢你

标签: assembly x86 bootloader osdev real-mode


【解决方案1】:

主要问题

在您的代码顶部执行以下操作:

bits    16
org     0
%include"Floppy16.inc"

start:  jmp main

%include"Floppy16.inc" 会将所有内容插入到文件floppy16.inc 中,就好像它是您的boot.asm 代码的一部分一样。问题是您的引导参数块 (BPB) 出现在任何代码之前,因此数据实际上将作为代码执行,因为引导加载程序将从物理地址 0x07c00 开始执行。我认为您可能应该这样做:

bits    16
org     0
start:  jmp main
nop               ; Place NOP so BPB starts at the 4th byte of binary file. 
                  ; relative(short) JMP is 2 bytes long. NOP acts as 1 byte padding.

%include"Floppy16.inc"

通过跳过文件 floppy16.inc 包含的 BPB 数据,您可以避免将数据作为代码执行。


在启动时,这个输出:

移除磁盘或其他媒体。按任意键重启

表明系统中可能已插入磁盘,但未找到可启动媒体。

我觉得奇怪的是,您似乎从汇编代码生成了一个二进制文件,但随后您使用了以下命令:

partcopy.exe boot.asm 0 200 -f0

这会将汇编器源代码 代码放入软盘的前512 个字节中。你想把你创建的二进制文件放到软盘上。我认为您应该使用:

partcopy.exe boot.bin 0 200 -f0

文件boot.bin 是从此命令创建的二进制文件:

nasm.exe -f bin boot.asm -o boot.bin

由于您将boot.asm 复制到软盘的引导扇区,该扇区的最后 2 个字节将不包含单词 0xAA55,因此不会被检测为可引导软盘。如果您的虚拟机上没有其他可启动媒体,您将收到有关删除媒体并重新启动的错误。


其他问题

cmets中提到的F​​ifoernik:

不相关但仍然...不要在奇数地址初始化您的堆栈指针!最好使用偶地址 mov sp, 0xFFFE

在过去的几天里,我写了一个Stackoverflow answer,也讨论了这个问题。我可能建议将 SP 设置为 0x0000。如果在真正的 8086 处理器上运行,与奇数字边界(如 0xffff)对齐的堆栈将严重影响性能。将 SP 设置为零有效,因为它是偶数地址,并且第一次将字压入堆栈会使 SP 先减 2,然后再写入该值。推送的第一个单词将在 SS:0xfffe 。


因为您的代码无论如何都不会在低于 386 的任何设备上运行,因为您有:

mov     fs, ax
mov     gs, ax

fsgs 寄存器是在 386 处理器中引入的。您的代码无法在真正的 8086/8088/80188/80286 处理器上运行。这可能是设计使然,但我觉得我应该提一下。


由于您使用像lodsb 这样的指令,您应该考虑设置方向标志。在您的情况下,您似乎依赖于向前移动,因此我建议我们在引导加载程序开头附近使用 CLD 指令。你不能保证它会被正确设置。


您的代码似乎破坏了 DL 的内容。 BIOS 将通过 DL 将引导驱动器传递给您的引导加载程序。您可能会考虑保存它,以便它可以用于从已引导的驱动器中读取扇区。您可能正在考虑这一点,但如果没有看到 floppy16.inc 的内容,这并不明显

【讨论】:

  • 未对齐的堆栈将导致所有 x86 CPU 的性能下降,但最新的 Intel CPU(Nehalem 或更高版本)除外。即使是较晚的 CPU 也可能会遭受跨越缓存行的访问,但对于典型的堆栈使用而言,它应该不重要。
  • @RossRidge :你说的很对。 8086 特别需要大约 4 个时钟周期来访问未对齐的堆栈,这在那些古老的处理器上可能相当大,这就是为什么我更倾向于为该处理器提及它。
  • 好吧,检查我的更新。我可能是盲人,因为我没有看到它。但即使我使用 .bin 扩展名,它也是一样的。 这是来自 PARTCOPY 程序的问题吗?还是 VMWARE 程序?或者可能是 NASM!? 但是当我使用 Windows 的选项将图像复制到文件并通过十六进制编辑器读取它时,我在内容中找到了字符串“删除磁盘或其他媒体。按任意键重新启动”。我也许应该使用第三方格式化程序?
  • @LukaAnđelković 怀疑这个问题是 VMWARE 或 NASM 中的错误。使用 VMWare,您确定您正确设置了软盘驱动器,并且它的大小正确吗? Partcopy 可能是罪魁祸首,但我从未使用过它。很难说,因为您不允许我们看到floppy.inc,所以我无法在这里真正测试它。如果您通过添加floppy.inc 的内容来修改您的问题,我将能够测试。就目前而言,您的软盘表现得好像 VMWare 不理解它(可能是您的配置错误)或者软盘映像本身是坏的。
  • @LukaAnđelković 是的,我做到了,这就是我知道您的 floppy16.inc 中的内容的方式。现在您是否阅读了我所说的在跳跃之前将其包括在内的内容?请参阅我更新的答案。关于跳过引导参数块。当 BIOS 开始执行您的引导扇区时,它会将您的引导参数块作为代码执行,这将是令人讨厌的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-27
  • 2017-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多