assembly 如何修复尝试读取扇区时的磁盘读取错误

xmd2e60i  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(165)

我正在使用这个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

    . . .

其他编辑

我很确定ah0xc。我这样运行:

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

yhuiod9q

yhuiod9q1#

当我 Boot 它时,它给我一个磁盘读取错误。
这将是最有用的显示我们的实际 * 状态字节 *,BIOS返回的AH寄存器时,进位标志是设置返回!
请阅读磁盘读取错误,而载入扇区到内存的解释和工作代码.

[org 0x7c00]
KERNEL_OFFSET equ 0x1000

    mov [BOOT_DRIVE], dl

    mov bp, 0x9000
    mov sp, bp

字符串
当BIOS将您的 Bootstrap 放入内存中时,您可以确定的唯一寄存器是保存 driveID 的DL。由于段寄存器在真实的模式编程中非常重要,因此您必须正确设置这些寄存器。根据您的[org 0x7c00],接下来是您必须写入的内容:

[org 0x7C00]
KERNEL_OFFSET equ 0x1000

  xor  ax, ax
  mov  ds, ax
  mov  es, ax
  mov  ss, ax            ; Keep these two together and
  mov  sp, 0x9000        ;  very importantly in this order
  mov  [BOOT_DRIVE], dl


我建议您将当前的 disk_load 过程替换为答案中提供了链接的那个过程,并确保正确地调用它。

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 )


在屏幕上显示临时消息是一种很好的调试技术,但不要忘记,print_string 过程会破坏从BIOS获得的进位标志。ReadSectors函数02 h.
要成功检查进位标志,请使用pushfpopf,如下所示:

mov  ah, 02h     ; BIOS.ReadSectors
  int  0x13
  pushf
  mov  bx, message
  call print_string
  popf
  jc   disk_error  ; Jump if error ( i.e. carry flag set )


这将保留堆栈上的进位标志。如果你不能确定 print_string 已经保留了AX,那么在这里以同样的方式保留AX。

相关问题