我编写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为零、清除方向标志等)
我想知道如何解决这个问题的几个指针。
1条答案
按热度按时间mutmk8jj1#
一些BIOS不允许使用
int 13h/ah=42h
一次阅读超过127个扇区。我建议将KERNEL_SIZE_SECTORS
设置为127而不是128。在其他地方(但不是我所经历的)有人建议,在执行磁盘读取之前,有些BIOS需要您将ES设置为与DAP的段字段中指定的值相同的值。在您的情况下,建议在启动读取之前将ES设置为0x07c0,以匹配磁盘地址包(DAP)中的段值。