Int 13h 扩展的 readDisk 例程不运行
Int 13h extended readDisk routine not functioning
我一直在尝试使用扩展读取功能 AH = 42H
和 INT 13H
读取引导加载程序代码 (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。您的磁盘重置 Int 13h/AH=0h call does this correctly, but your Int 13/AH=42h 扩展磁盘读取没有。
我一直在尝试使用扩展读取功能 AH = 42H
和 INT 13H
读取引导加载程序代码 (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。您的磁盘重置 Int 13h/AH=0h call does this correctly, but your Int 13/AH=42h 扩展磁盘读取没有。