assembly 在真实的硬件上引导时,引导加载程序收到磁盘读取错误,但在vmware、qemu和bochs上未收到

jfewjypa  于 2023-03-02  发布在  其他
关注(0)|答案(1)|浏览(120)

我编写x86引导装载程序已经有一段时间了,并且已经验证了我的引导装载程序可以在bochs和qemu沿着vmware上工作,但是,我在真实的硬件(Thinkpad T400)上得到了一个磁盘读取错误,错误代码为0x0880,而在qemu上没有。

[bits 16]
[extern kernel]
[global isr_stub_table]
[global IDT_load]

[extern FortressLoader_IdtInit]
[extern FortressLoader_ChecmMemMap]

[extern X86TTY_Init]
[extern X86TTY_Clear]
[extern printf]

[global FortressLoader_HeapStart]
[global FortressLoader_HeapEnd]

[global startKernel]

section .boot
global boot

KERNEL_SIZE_SECTORS equ 128

jmp boot
TIMES 3-($-$$) DB 0x90

OEMname:           db    "mkfs.fat"
bytesPerSector:    dw    512
sectPerCluster:    db    1
reservedSectors:   dw    1
numFAT:            db    2
numRootDirEntries: dw    224
numSectors:        dw    2880
mediaType:         db    0xf0
numFATsectors:     dw    9
sectorsPerTrack:   dw    18
numHeads:          dw    2
numHiddenSectors:  dd    0
numSectorsHuge:    dd    0
driveNum:          db    0
reserved:          db    0
signature:         db    0x65
volumeID:          dd    0x2d7e5a1a
volumeLabel:       db    "NO NAME    "
fileSysType:       db    "FAT12   "

boot:
    cld                        ;Clear direction flag
    
    xor    ax, ax
    mov    ds, ax 
    mov    es, ax
    mov    ss, ax
    mov    fs, ax
    mov    gs, ax
    mov    sp, 0x7c00
    mov    di, 0x7c00

    cli

    mov    ah, 0x41             ;Check to make sure 13h extensions
    mov    bx, 55AAh            ;CONT: are enabled by the BIOS
    int    0x13                 ;Call the disky wisky interrupt 🥺

    jc     dskDrvNope           ;Print no disk support msg
    cmp    bx, 0xAA55           ;Check if 13h supported by BIOS
    jnz    dskDrvNoExtAtALl

    mov    bx, diskNoError      ;
    call   print

    mov    [disk], dl
    mov    ax, 0x2401
    int    0x15
 
    mov    ax, 0x3              ;Set the VGA mode, unknown at boot
    int    0x10
 
    mov    ah, 42h
    mov    dl, [disk]
    mov    si, dap
    int    0x13
 
    jc     disk_err             ;Jump if disk read error
    jmp    disk_target          ;

dskDrvNope:
    mov    bx, disk_no_extensions
    call   print
    hlt
dskDrvNoExtAtALl:
    mov    bx, disk_no_extatall
    call   print
    hlt

print:
    pusha
start:
    mov    al, [bx] 
    cmp    al, 0 
    je     done
 
    mov    ah, 0x0e
    int    0x10 
 
    add    bx, 1
    jmp    start
 
done:
    popa
    ret
 
print_nl:
    pusha  
 
    mov    ah, 0x0e
    mov    al, 0x0a
    int    0x10
    mov    al, 0x0d
    int    0x10
 
    popa
    ret
 
print_hex:
    pusha
 
    mov    cx, 0
 
hex_loop:
    cmp    cx, 4
    je     end
 
    mov    ax, dx
    and    ax, 0x000f
    add    al, 0x30 
    cmp    al, 0x39
    jle    step2
    add    al, 7
 
step2:
    mov    bx, HEX_OUT + 5
    sub    bx, cx
    mov    [bx], al
    ror    dx, 4
 
    add    cx, 1
    jmp    hex_loop
 
end:
    mov    bx, HEX_OUT
    call   print
 
    popa
    ret
 
disk_err:                      ;Label for any disk errors
    mov    bx, disk_read_error ;Print the disk error
    call   print
    call   print_nl
    mov    dh, ah              ;Load error code in ah register
    call   print_hex
    jmp    $
 
disk:
    db     0x0

dap:
    db     0x10
    db     0
    dw     KERNEL_SIZE_SECTORS
    dw     0                   ;
    dw     0x07e0              ;value recommended by a friend
    dq     1                   ;start second sector read
 
HEX_OUT:
    db     '0x0000',0
 
disk_read_error:    db "Disk read error!", 0
disk_no_extensions: db "no disk ah=42h", 0
disk_no_extatall:   db "no bios ah=42h", 0
diskNoError:        db "Using bios extensions", 0

times 510 - ($-$$)  db 0
    dw 0xAA55

%include "./fortressloader/memory.asm"
%include "./fortressloader/memmap.asm"
%include "./fortressloader/multiboot.asm"
 
GDT_START:
    dq     0x0
GDT_CODE: 
    dw     0xffff 
    dw     0x0 
    db     0x0 
    db     10011010b
    db     11001111b
    db     0x0
GDT_DATA:
    dw     0xFFFF
    dw     0x0
    db     0x0
    db     10010010b
    db     11001111b
    db     0x0
GDT_END:
GDT_POINTER
    dw     GDT_END - GDT_START - 1
    dd     GDT_START
 
CODE_SEG equ GDT_CODE - GDT_START
DATA_SEG equ GDT_DATA - GDT_START

disk_target
    call   BiosGetMemorySize64MB  
                               ;Load the memory size
    mov    [mbInfo+mbInfo.memoryHi], bx
    mov    [mbInfo+mbInfo.memoryLo], ax
    mov    word [mbInfo+mbInfo.bootDevice], 0x0
    mov    edi, 0x2000

    call   BiosGetMemoryMap
    mov    word [mbInfo+mbInfo.mmap_length], ax
    mov    word [mbInfo+mbInfo.mmap_addr], 0x2000

    cli                        ;Clear the interrupts
    lgdt   [GDT_POINTER]       ;Load the GDT using a gdt pointer
    mov    eax, cr0
    or     eax, 0x1
    mov    cr0, eax
    jmp    CODE_SEG:boot2

[bits 32]
startKernel:
boot2:
    mov    ax, DATA_SEG
    mov    ds, ax
    mov    es, ax
    mov    fs, ax
    mov    gs, ax
    mov    ss, ax
    mov    esi, loaded_msg
    mov    ebx, 0xb8000
.loop:                         ;Print a message using a loop
    lodsb
    or     al, al
    jz     load_kernel         ;Load kernel when msg finished
    or     eax,0x0F00
    mov    word [ebx], ax
    add    ebx,2
    jmp    .loop
load_kernel:
    mov    esp, kernel_stack_top
                               ;Load the stack to call C functions

    call   X86TTY_Init         ;Initialize the TTY
    call   X86TTY_Clear        ;Clear everything on the screen
    call   FortressLoader_IdtInit
                               ;Initialize the IDT    

    mov    eax, 0x1BADB002     ;Multiboot magic number
    mov    ebx, mbInfo
    mov    ebx, 0

    push   eax
    push   ebx

    call   kernel              ;Call the actual kernel
halt:    
    cli
    hlt

loaded_msg:db "Operating system loaded",0          
                               ;Message here to verify disk read
 
section .bss
align 4
kernel_stack_bottom: equ $     ;equ the current address for the stack
    resb             16384     ;Use 16kb for stack size
kernel_stack_top:              ;Top of the stack

section .text

我最初认为这个错误是BIOS不支持int 0x13 ah=42h扩展,因为我听说有些BIOS不支持磁盘扩展,所以我不得不使用CHS方法(我宁愿不使用CHS)。然而,当添加函数来检查ah=42h读支持时,没有任何变化,表明BIOS确实支持它。
我还搜索了我的代码在真实的硬件上不起作用的原因,并遵循了所有这些原因(例如:确保DS为零、清除方向标志等)
我想知道如何解决这个问题的几个指针。

mutmk8jj

mutmk8jj1#

一些BIOS不允许使用int 13h/ah=42h一次阅读超过127个扇区。我建议将KERNEL_SIZE_SECTORS设置为127而不是128。
在其他地方(但不是我所经历的)有人建议,在执行磁盘读取之前,有些BIOS需要您将ES设置为与DAP的段字段中指定的值相同的值。在您的情况下,建议在启动读取之前将ES设置为0x07c0,以匹配磁盘地址包(DAP)中的段值。

相关问题