我正在使用这个tutorial构建一个简单的操作系统。我的问题是它调用了一个磁盘加载函数,当我 Boot 启动它时,它给了我一个磁盘读取错误。下面是我的boot_sect.asm代码:
[org 0x7c00]
KERNEL_OFFSET equ 0x1000
mov [BOOT_DRIVE], dl
mov bp, 0x9000
mov sp, bp
mov bx, MSG_REAL_MODE
call print_string
call load_kernel
mov bx, MSG_LOAD_KERNEL
call print_string
call switch_to_pm
jmp $
%include "print_string.asm"
%include "disk_load.asm"
%include "gdt.asm"
%include "print_string_pm.asm"
%include "switch_to_pm.asm"
[bits 16]
load_kernel:
mov bx, MSG_LOAD_KERNEL
call print_string
mov bx, KERNEL_OFFSET
mov dh, 15
mov dl, [BOOT_DRIVE]
call disk_load
ret
[bits 32]
BEGIN_PM:
mov ebx, MSG_PROT_MODE
call print_string_pm
call KERNEL_OFFSET
jmp $
BOOT_DRIVE db 0
MSG_REAL_MODE db "Started in 16-bit Real Mode", 0
MSG_PROT_MODE db "Successfully landed in 32-bit Protected Mode", 0
MSG_LOAD_KERNEL db "Loading kernel into memory", 0
; Padding
times 510-($-$$) db 0
dw 0xaa55
字符串
我的disk_load.asm:
; load DH sectors to ES:BX from drive DL
disk_load :
push dx ; Store DX on stack so later we can recall
; how many sectors were request to be read ,
; even if it is altered in the meantime
mov ah, 0x02 ; BIOS read sector function
mov al, dh ; Read DH sectors
mov ch, 0x00 ; Select cylinder 0
mov dh, 0x00 ; Select head 0
mov cl, 0x02 ; Start reading from second sector ( i.e.
; after the boot sector )
int 0x13; BIOS interrupt
jc disk_error ; Jump if error ( i.e. carry flag set )
pop dx ; Restore DX from the stack
cmp dh, al ; if AL ( sectors read ) != DH ( sectors expected )
jne disk_error2 ; display error message
ret
disk_error :
mov bx , DISK_ERROR_MSG
call print_string
jmp $
disk_error2 :
mov bx , DISK_ERROR_MSG2
call print_string
jmp $
; Variables
DISK_ERROR_MSG db " Disk read error 1 !" , 0
DISK_ERROR_MSG2 db " Disk read error 2 !" , 0
型
这篇文章说,我可能需要es
为零,但当我把
xor bx, bx
mov es, bx
型
上面的int 0x13
,它只是挂在中断.我怎么能修复这个?
已编辑
在这个例子中,我让它在中断后显示hello
,但是,它不显示它,除非我删除xor bx, bx mov es, bx
,所以这就是为什么我认为它卡在那里:
; load DH sectors to ES:BX from drive DL
disk_load :
push dx ; Store DX on stack so later we can recall
; how many sectors were request to be read ,
; even if it is altered in the meantime
mov ah, 0x02 ; BIOS read sector function
mov al, dh ; Read DH sectors
mov ch, 0x00 ; Select cylinder 0
mov dh, 0x00 ; Select head 0
mov cl, 0x02 ; Start reading from second sector ( i.e.
; after the boot sector )
xor bx, bx
mov es, bx
int 0x13; BIOS interrupt
mov bx, message ; This should print `hello` after the interrrupt
call print_string ;
jc disk_error ; Jump if error ( i.e. carry flag set )
pop dx ; Restore DX from the stack
cmp dh, al ; if AL ( sectors read ) != DH ( sectors expected )
jne disk_error2 ; display error message
ret
. . .
型
其他编辑
我很确定ah
是0xc
。我这样运行:
qemu-system-x86_64 os-image -s & gdb
target remote localhost:1234
info register ah
型
并且输出是ah 0xc 12
个
另外,我的编译命令是:
i386-elf-gcc -ffreestanding -c kernel.c -o kernel.o
ld -m elf_i386 -o kernel.bin -Ttext 0x1000 kernel.o --oformat binary
nasm boot_sect.asm -f bin -o boot_sect.bin
cat boot_sect.bin kernel.bin > os-image
qemu-system-x86_64 os-image
型
1条答案
按热度按时间yhuiod9q1#
当我 Boot 它时,它给我一个磁盘读取错误。
这将是最有用的显示我们的实际 * 状态字节 *,BIOS返回的AH寄存器时,进位标志是设置返回!
请阅读磁盘读取错误,而载入扇区到内存的解释和工作代码.
字符串
当BIOS将您的 Bootstrap 放入内存中时,您可以确定的唯一寄存器是保存 driveID 的DL。由于段寄存器在真实的模式编程中非常重要,因此您必须正确设置这些寄存器。根据您的
[org 0x7c00]
,接下来是您必须写入的内容:型
我建议您将当前的 disk_load 过程替换为答案中提供了链接的那个过程,并确保正确地调用它。
型
在屏幕上显示临时消息是一种很好的调试技术,但不要忘记,print_string 过程会破坏从BIOS获得的进位标志。ReadSectors函数02 h.
要成功检查进位标志,请使用
pushf
和popf
,如下所示:型
这将保留堆栈上的进位标志。如果你不能确定 print_string 已经保留了AX,那么在这里以同样的方式保留AX。