当我尝试使用 BIOS 从磁盘读取时,出现错误 0x0C80,这是我的代码:
disk_load:
push dx
mov ah, 0x42 ; BIOS extended read routine
mov dl, 0x80 ; Drive number (0x80 for the first HDD)
mov si, DAP ; DS:SI -> Disk Address Packet
int 0x13 ; BIOS Disk interrupt
jc disk_error
pop dx
cmp dh, al
jne disk_sectors_error
jmp disk_success
jmp disk_exit
DAP:
db 0x10 ; Size of DAP
db 0x00 ; Reserved
dw 16 ; Number of sectors to read, equal to value in dh
dw 0x1000 ; Offset to buffer
dw 0x0000 ; Segment of buffer
dq 1 ; Starting absolute block number (LBA)
disk_success:
mov bx, SUCCESS_MSG
jmp disk_exit
disk_error:
mov bx, DISK_ERR_MSG
call print_string
mov dh, ah ; AH contains the error code
call print_hex
jmp disk_loop
disk_sectors_error:
mov bx, SECTORS_ERR_MSG
call print_string
SUCCESS_MSG:
db "Disk was successfully read ", 0
DISK_ERR_MSG:
db "Disk read error! Error code: ", 0
SECTORS_ERR_MSG:
db "Incorrect number of sectors read ", 0
disk_loop:
jmp $
disk_exit:
ret
[org 0x7c00]
KERNEL_OFFSET equ 0x1000 ; Смещение в памяти, из которого мы загрузим ядро
mov [BOOT_DRIVE], dl ; BIOS stores our boot drive in DL, so it ’s
; best to remember this for later. (Remember that
; the BIOS sets us the boot drive in 'dl' on boot)
mov bp, 0x9000 ; Устанавливаем стек
mov sp, bp
call load_kernel ; Загружаем ядро
call switch_to_pm ; Переключаемся в Защищенный Режим
jmp $
%include "OS/boot/print_string.asm" ; ф. печати строки
%include "OS/boot/print_hex.asm" ; ф. печати 16-ричного числа
%include "OS/boot/disk_load.asm" ; ф. чтения диска
%include "OS/boot/print_string_pm.asm" ; ф. печати строки (32PM)
%include "OS/boot/switch.asm" ; ф. переключения в 32PM
%include "OS/boot/gdt.asm" ; таблица GDT
[bits 16]
load_kernel:
mov bx, KERNEL_OFFSET
mov dh, 16
mov dl, [BOOT_DRIVE]
call disk_load
ret
[bits 32] ; Сюда мы попадем после переключения в 32PM
BEGIN_PM:
mov esp, 0x90000
call KERNEL_OFFSET ; Переходим в адрес, по которому загрузился код ядра
jmp $
BOOT_DRIVE: db 0
times 510-($-$$) db 0
dw 0xaa55
我需要读取前16个扇区并加载内核,然后进入32位保护模式并执行它
我从Github
获取了代码的基础我尝试在互联网上搜索,但找不到任何可以帮助我的东西:(
disk_load
call print_string mov dh, ah ; AH contains the error code call print_hex
您没有向我们展示“print_string.asm”或“print_hex.asm”的内容,因此我们无法检查 AH 是否在 print_string 调用中幸存下来或 print_hex 是否需要 DH 输入!
来自 IBM/MS INT 13 Extensions 的错误代码 0Ch 读取“不支持的轨道或无效媒体”。
它可能源于您使用硬编码的驱动器号,如
mov dl, 0x80 ; Drive number (0x80 for the first HDD)
中所示。你did传递给你的disk_load例程,BIOS给你的BOOT_DRIVE代码,那你为什么要覆盖它?cmp dh, al jne disk_sectors_error ... disk_sectors_error: mov bx, SECTORS_ERR_MSG call print_string SUCCESS_MSG: db "Disk was successfully read ", 0
“ExtendedRead”函数不会报告通过 AL 寄存器成功传输的块数!在 DAP 中查找此信息。
当发生可能的失败时,您打印一条合适的消息,但允许 CPU 开始执行文本消息!这些消息属于最终的
disk_exit:
ret
下面。这样,disk_sectors_error代码就可以正确地落入disk_loop:
jmp $
代码中。
永远不要假设这些扩展可用!它们具有“安装检查”功能,可让您了解其功能。使用它:
mov dl, [BOOT_DRIVE]
test dl, dl
jns UseCHS ; Not meant for drives [00h,7Fh]
mov bx, 55AAh
mov ah, 41h
int 13h ; -> AX BX CX DH CF
jc UseCHS ; Extensions not supported
cmp bx, 0AA55h
jne UseCHS ; Not installed
shr cx, 1
jnc UseCHS ; Functions 42h, 43h, 44h, 47h, 48h not supported
如果扩展不可用,则使用合适的消息中止或退回到正常的 CHS (CylinderHeadSector) 功能。
BIOS 将我们的启动驱动器存储在 DL 中,因此最好记住这一点以供以后使用。 (请记住,BIOS 在启动时将启动驱动器设置为“dl”)
您的评论是对的,但比这更深入。 DL 是唯一一个在引导加载程序开始时保证保存有意义的值的寄存器。您必须自己设置段寄存器和堆栈指针,并且不要相信 BIOS 会为您完成这些操作。
%include "OS/boot/print_string_pm.asm"%include "OS/boot/switch.asm"%include "OS/boot/gdt.asm"
切换到保护模式不是引导加载程序应该做的事情!它属于你的内核的设置代码。
%包括“OS/boot/print_string.asm”
%包括“OS / boot / print_hex.asm”disk_load%include "OS/boot/disk_load.asm"
为什么有这么多包含文件?他们所做的小工作并不能证明单独的文件是合理的,更重要的是,他们引诱您犯这些错误。我指的是引导加载程序和
之间以及 disk_load 和 print_hex 之间的参数不匹配。
只需将其实际源文本插入引导加载程序源即可。
[org 0x7c00]
KERNEL_OFFSET equ 0x1000
cld
xor ax, ax
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x9000
mov [BOOT_DRIVE], dl
mov bx, KERNEL_OFFSET
mov cx, 16
call disk_load
jmp 0:KERNEL_OFFSET
; ---------------------------------
; IN (ax:bx,cx,dl)
disk_load:
mov si, DAP ; DS:SI -> Disk Address Packet
mov [si+2], cx ; Count
mov [si+4], bx ; Offset
mov [si+6], ax ; Segment
test dl, dl
jns UseCHS ; Not meant for drives [00h,7Fh]
mov bx, 55AAh
mov ah, 41h ; BIOS.InstallationCheck
int 13h ; -> AX BX CX DH CF
jc UseCHS ; Extensions not supported
cmp bx, 0AA55h
jne UseCHS ; Not installed
shr cx, 1
jnc UseCHS ; Functions 42h, 43h, 44h, 47h, 48h not supported
mov ah, 0x42 ; BIOS.ExtendedRead
int 0x13 ; -> AH CF
jc disk_error
cmp [si+2], cx
je disk_success
disk_sectors_error:
mov si, SECTORS_ERR_MSG
call print_string
jmp $
disk_error:
push ax ; AH contains the error code
mov si, DISK_ERR_MSG
call print_string
pop ax
call print_hex
jmp $
UseCHS:
...
disk_success:
mov si, SUCCESS_MSG
; ----------------------------
; IN (si) OUT (si) MOD (ax)
print_string:
lodsb
mov ah, 0Eh
.next:
int 10h
lodsb
cmp al, 0
jne .next
ret
; ----------------------------
; IN (ax)
print_hex:
...
ret
; ----------------------------
DAP:
db 16 ; Size of DAP
db 0 ; Reserved
dw 0 ; Number of sectors to read
dw 0 ; Offset to buffer
dw 0 ; Segment of buffer
dq 1 ; Starting absolute block number (LBA)
SUCCESS_MSG:
db "Disk was successfully read ", 0
DISK_ERR_MSG:
db "Disk read error! Error code: ", 0
SECTORS_ERR_MSG:
db "Incorrect number of sectors read ", 0
BOOT_DRIVE:
db 0
; ----------------------------
times 510-($-$$) db 0
dw 0xAA55