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。谢谢您,它解决了我的问题。是的,注意到,我现在正在存储驱动器号以备将来使用。