首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我的引导加载器无法正确加载完整文件(FAT16)

我的引导加载器无法正确加载完整文件(FAT16)
EN

Stack Overflow用户
提问于 2021-03-30 07:54:44
回答 1查看 194关注 0票数 1

我已经为一个小型操作系统编写了一段时间,我一直使用VM测试它,特别是它在QEMU、VMWare和VirtualBox上工作。内核希望从HDD引导,所以为了在真正的硬件上测试它,我将它烧到一个真正的硬盘上,并将它连接到一个真正的pc上。从此就成了一场灾难!一切都在起作用。我已经部分修复了我可以找到的所有错误,但我真的不知道是什么原因造成的: VBR在被MBR加载之后,只能加载第二阶段引导加载器的一部分;在BOCHS中,它只加载第一个集群,但是在真正的pc中,内存中加载的代码更少。所有处理FAT16的代码都在一个文件中,但是它仍然太大,不能在这里发布,所以我将在GitHub上提供它的链接。此文件(/boot/include/fat16.inc)由主VBR文件(/boot/src/vbr.asm)包含。一些初始化在vbr.asm中可能会丢失,但由于空间限制,它们在MBR文件(/boot/src/mbr.asm)中被处理。

编辑

如果出于某些原因,GitHub回购丢失了,我将为未来的读者张贴for 16.inc的代码:

代码语言:javascript
复制
%ifndef __FAT12_INC__
%define __FAT12_INC__

; this file relies on a word variable called partition_offset
; partition_offset should contain the address in memory of
; the current partition entry in the table

bits 16

%define ROOT_OFFSET Mem.Loader.FAT16.Data
%define ROOT_SEG LIN_TO_FAR_ADDR(ROOT_OFFSET)

%define FAT_OFFSET Mem.Loader.FAT16.Data
%define FAT_SEG LIN_TO_FAR_ADDR(FAT_OFFSET)

%include "include/disk.inc"

;*********************************;
; Sets Rot Directory informations ;
; Returns:                        ;
;   ecx => location in sectors.   ;
;   eax => size in sectors        ;
;*********************************;
GetRootInfo:
    ; clear registers
    xor eax, eax
    xor ecx, ecx

    ; compute location of root directory in sectors and store in "ecx" 
    mov al, byte [bpb_NumberOfFATs]     ; number of FATs
    mul word [bpb_SectorsPerFAT]        ; sectors used by FATs
    add ax, word [bpb_ReservedSectors]  ; reserved sectors
    mov cx, ax                          ; move into cx
    mov ax, word [partition_offset]
    add cx, word [eax + 8]              ; offset from partition information

    ; compute size of root directory in sectors and store in "ax" 
    mov ax, 32                          ; 32 byte directory entry
    mul word [bpb_RootEntries]          ; total size of directory
    div word [bpb_BytesPerSector]       ; sectors used by directory

    ret

;***************************************;
; Load Root Directory Table to ROOT_SEG ;
;***************************************;
LoadRoot:
    call GetRootInfo

    ; read Root into memory at ROOT_SEG
    mov dl, byte [bpb_DriveNumber]
    mov ebx, dword ROOT_SEG
    call ReadSectorsLBA
    ret

;****************************;
; Loads FAT table to FAT_SEG ;
;****************************;
LoadFAT:
    pushad

    ; clear registers
    xor ax, ax
    xor cx, cx

    ; compute size of FAT and store in "ax" 
    mov ax, word [bpb_SectorsPerFAT]    ; number of FATs

    ; compute location of FAT and store in "ecx"
    mov cx, word [partition_offset]
    mov cx, word [ecx + 8]              ; offset from partition information
    add cx, word [bpb_ReservedSectors]

    ; read FAT into memory at FAT_SEG
    mov dl, byte [bpb_DriveNumber]
    mov ebx, dword FAT_SEG
    call ReadSectorsLBA

    popad
    ret

;***********************************************;
; Search for filename in root table             ;
; Parameters:                                   ;
;   si => File name                             ;
; Returns:                                      ;
;   ax => File index number in directory table. ;
;   di => Location of the file root entry       ;
;***********************************************;
FindFile:
    ; store registers   
    push cx
    push bx
    push es

    mov bx, si                      ; save filename for later

    push ROOT_SEG >> 16             ; locate first root entry
    pop es
    mov di, ROOT_SEG                ; ES:DI is memory location of root dir
    mov cx, word [bpb_RootEntries]  ; load loop counter
    ; browse root directory for binary image
    cld                             ; clear direction flag
.loop:
    push cx
    mov cx, 11                      ; eleven character name. Image name is in SI
    mov si, bx                      ; image name is in BX
    push di
    rep cmpsb                       ; test for entry match [ DS:SI - ES:DI ]
    pop di
    je .Found
    pop cx
    add di, 32                      ; queue next directory entry
    loop .loop

.NotFound:
    ; set error code
    mov ax, -1
    ; restore registers and return
    pop es
    pop bx
    pop cx
    ret

.Found:
    ; return value into AX contains entry of file
    pop ax
    ; restore registers and return
    pop es
    pop bx
    pop cx
    ret

;**********************************************;
; Gain information about the file to be loaded ;
; Parameters:                                  ;
;   edi => Location of the file root entry     ;
;**********************************************;
PrepareFile:
    ; get starting cluster
    push word ROOT_SEG >> 16
    pop es
    mov ax, word [es:edi + 0x1A]   ; retrive cluster from root entry
    mov word [cluster], ax

    ; get 0th cluster address
    call GetRootInfo
    add eax, ecx
    mov dword [first_cluster_sector], eax

    call LoadFAT
    ret

;*********************************************;
; Read the current selected cluster in memory ;
; Parameters:                                 ;
;   ebx => Buffer to load file to             ;
;*********************************************;
LoadNextCluster:
    ; zero out registers for calculations
    xor cx, cx
    xor dx, dx

    ; convert the cluster in lba
    mov ax, word [cluster]
    sub ax, 2
    mov dl, byte [bpb_SectorsPerCluster]
    mul dx
    xchg cx, ax
    add ecx, dword [first_cluster_sector]

    ; sets the others parameters and read the disk
    mov dl, byte [bpb_DriveNumber]
    mov al, byte [bpb_SectorsPerCluster]
    call ReadSectorsLBA

    ; get next cluster from fat table
    xor eax, eax
    mov ax, word [cluster]
    mov dx, 2
    mul dx ; since fat table is an array of words (2 byte)

    push word FAT_SEG >> 16
    pop es
    mov dx, word [dword es:eax]
    mov word [cluster], dx

    ret

;*******************************************************;
; Check if the current reading file has been compleated ;
; Returns:                                              ;
;   cf => set on compleated                             ;
;*******************************************************;
FileReadCompleated:
    ; test if it was the last cluster
    cmp word [cluster], 0xFFFF
    je .complete
    cmp word [cluster], 0xFFF8
    je .complete

.incomplete:
    clc ; clear carry flag
    ret
.complete:
    stc ; set carry flag
    ret

;************************************;
; Load file                          ;
; Parameters:                        ;
;   es:si => File name               ;
;   ebx => Buffer to load file to    ;
; Returns:                           ;
;   ax => -1 on error, 0 on success  ;
;************************************;
LoadFile:
.findFile:
    ; find file using name in es:si
    call FindFile
    cmp ax, -1
    je .done ; file not found

.loadFilePre:
    call PrepareFile

.nextCluster:
    call LoadNextCluster

    call FileReadCompleated
    jc .success

    ; increase address
    xor eax, eax
    mov ax, word [bpb_SectorsPerCluster]
    mul word [bpb_BytesPerSector]
    mov ecx, eax
    shr eax, 4
    shl eax, 16
    and ecx, 0xF
    or eax, ecx
    add ebx, eax
    ; check if riporto
    mov eax, ebx
    and eax, (1 << 4)
    cmp eax, 0
    je .nextCluster
    ; fix riporto
    xor ebx, 1 << 4
    add ebx, 1 << 16
    jmp .nextCluster

.success:
    xor ax, ax
.done
    ret

cluster dw 0x0000
first_cluster_sector dd 0x00000000


%endif ; __FAT12_INC__
EN

回答 1

Stack Overflow用户

发布于 2021-04-01 08:06:11

这并不是我所拥有的问题的完全解决方案,但我还是想把它作为一个答案来发布,因为它对未来的读者是有用的。

事实上,在我的例子中,int 13.42破坏了ebx的内容。

现在我可以在BOCHS和Microsoft中启动我的映像,它仍然不能在真正的硬件上启动,但这肯定是一件重要的事情。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66866840

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档