Assembly Int 13h扩展读取磁盘例程不工作

Assembly Int 13h扩展读取磁盘例程不工作,assembly,x86,bootloader,disk,osdev,Assembly,X86,Bootloader,Disk,Osdev,我一直在尝试使用扩展读取函数AH=42H和int13h读取引导加载程序代码(MBR)中的几个扇区 但不会显示错误,并且不会读取扇区。 到目前为止,在使用Bochs和Qemu进行调试时,我注意到: (我相应地设置了dl寄存器) 未设置进位标志,因此没有错误 在第二个扇区中不读取任何内容,即0x7e00用0填充 这也意味着jmp sect2之后的任何代码都不会被执行。 我做错了什么 下面是readDisk例程的代码: readDisk: pusha push ds push

我一直在尝试使用扩展读取函数
AH=42H
int13h
读取引导加载程序代码(MBR)中的几个扇区 但不会显示错误,并且不会读取扇区。
到目前为止,在使用Bochs和Qemu进行调试时,我注意到:
(我相应地设置了dl寄存器)

未设置进位标志,因此没有错误 在第二个扇区中不读取任何内容,即0x7e00用0填充
这也意味着
jmp sect2
之后的任何代码都不会被执行。
我做错了什么

下面是readDisk例程的代码:

readDisk:

    pusha
    push ds
    push si

    mov word [DAP_START_SECTOR] , cx
    mov word [DAP_NUM_SECTORS] , ax
    mov word [DAP_OFFSET], di
    mov word [DAP_SEGMENT], es
    xor ax,ax
    mov ds, ax
    mov si, DAP

    mov dl, 0x80
    ;0x80 for hard drive
    ;0x00 for first floppy
    mov ax, 0x42
    int 13h
    jc fail

    pop si
    pop ds
    popa
    ret
align 4
DAP:
    DAP_SIZE:           db 0x10
    DAP_UNUSED:         db 0x00
    DAP_NUM_SECTORS:    dw 0x00
    DAP_PTR_TO_SECTOR: 
        DAP_OFFSET:     dw 0x00
        DAP_SEGMENT:    dw 0x00

    DAP_START_SECTOR:   dq 0x00

fail:
 mov si,DISKFAILMSG
 call printf
 mov dx,ax
 call printh
 jmp $
DISKFAILMSG db "disk read ERROR",0
以下是引导加载程序的代码:

[org 0x7c00]  ;start at 0x7c00
[bits 16]

section .data ; constants, put under the magic number, at the end
section .bss  ; variables, similarly at the end
section .text ; code

global main   ;main is global and is our entry point

main:
            ;clear the seg registers, to prevent any offset buffer

cli         ;clear interrupts

jmp 0x0000:ZeroSeg

ZeroSeg:
    xor ax,ax   ; clear ax
    mov ss,ax
    mov ds,ax
    mov es,ax
    mov fs,ax
    mov gs,ax

    ;cleared the seg

    mov sp, 0x7c00      ;0x7c00 = main?
    cld         ; clear the direction flag, which controlls the order of reading
                ; string
    sti         ; set interrupt
    push ax
    xor ax,ax
    ;mov dl, 10000000b
    int 13h
    jc fail
    pop ax






;mov al,2       ; read 2 sectors
;mov cl,2       ; sectors start from 1, sector 1 is bootloader, so read sector 2

mov ax,0x07e0
mov es,ax
xor di,di

mov ax, 0x0002      ; number of sectors read
mov cx, 0x0001  ;absolute number (not addr of start sector (sector 0 is bootloader here))


call readDisk


call loadE820
mov dx,ax       ;trial 1: received 6 entries
call printh

;TODO Configure Proper video modes
;call videoMode









jmp sect2       ; works if sect2 is read

%include "./printf.asm"
%include "./readDisk.asm"
%include "./printh.asm"
%include "./loadE820.asm"
;%include "./videoMode.asm"

%include "./gdt.asm"
;
;
;
times 510 - ($-$$) db 0 ;padding
dw 0xaa55               ;Magic number


;sector 2  

sect2:
    call EnableA20

    mov si, MESSAGE
    call printf

    call checklm

    mov si,DISKSUCCESSMSG
    call printf

    ;call keyb



;call videoMode
call enterProtected
;
;
;;*******************************TEST CODE********************************
;
;
;;call testvid32
;
mov si,DISKSUCCESSMSG
call printf


jmp $

%include "./TestA20.asm"
%include "./EnableA20.asm"

%include "./checklm.asm"
;
;
;
;
;
MESSAGE db "Hello, World!",0x0a,0x0d,0
DISKSUCCESSMSG db "Welcome to my first OS!",0ah,0dh,0



times 512-($-sect2) db 0

sect3:
%include "./enterProtected.asm"
keyb:
        mov ah,00h
        int 16h
        cmp ah,0
        je keyb
        ret
%include "./testvid32.asm"

虽然这可能是启动映像以及如何创建它或与未显示的代码相关的问题,但我怀疑真正的问题可能是以下错误:

mov ax, 0x42
int 13h
BIOS调用号0x42应为AH,而不是AX。应改为:

mov ah, 0x42
int 13h


虽然这不是您的问题,但在调用磁盘功能时,硬编码引导驱动器号通常不是一个好主意。您可以简单地使用BIOS传递给引导加载程序的DL中的值,而不是强制DL为0x80。磁盘重置调用可以正确执行此操作,但扩展磁盘读取无法正确执行。

mov
ss
后应立即接
mov
sp
@ecm:如果他没有将CLI作为第一条指令发出,则情况会是这样。对于CLI,他设置的顺序并不重要,因为在中断关闭的情况下,仅启动处理器就不允许在SS和SP的更新之间发生任何事情。我也注意到了这一点。为了避免原子性错误,不需要在SS之后进行SP更新,只需要引导加载程序以某种方式使其原子化。如果他在有缺陷的8088上运行,并且SS更新后指令的中断可能没有关闭,那么使用CLI也会起作用。@Michael Petch:在同一台机器上运行的调试器中运行加载程序(不是在它的外部)将导致先设置SS,而不设置SP。因此,即使中断被禁用,SP更改也应该在后续指令中完成。如果我们想挑剔,如果我们在CPU有缺陷的8088上运行,则必须使用CLI,因为在SS更新之后,并不是所有8088对指令禁用的中断。@Michael Petch:就我而言,我们应该同时执行
cli
和设置SS后立即设置SP。谢谢您,它解决了我的问题。是的,注意到,我现在正在存储驱动器号以备将来使用。