当前位置:  开发笔记 > 编程语言 > 正文

INT 0x13/AH = 0x02适用于软盘映像,但不能在闪存驱动器上刻录

如何解决《INT0x13/AH=0x02适用于软盘映像,但不能在闪存驱动器上刻录》经验,为你挑选了1个好方法。

我试图在x86程序集中创建一个简单的命令系统.命令系统是在0x1000:0000中加载的第二个阶段.要查看我的引导加载程序,请单击此stackoverflow问题.

这是第二阶段命令系统:


[BITS 16]
[ORG 0x0000]      

mov ax, cs
mov ds, ax   
xor cx, cx  
mov bx, welcome_msg
call str_prt
call new_line
mov bx, creator_msg
call str_prt
call new_line
mov bx, boot_msg
call str_prt
call new_line
mov bx, [buffer]

call new_line

mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
mov al, '>'
int 0x10

loop:
in al, 64h  
test al, 1    
je loop
xor ah, ah
int 0x16
call key_scan
jmp loop

key_scan:
cmp al, 0x08
je back_space
cmp al, 0x0d
je enter
cmp cx, 0x0015 
je end
mov ah, 0x0e
int 0x10
mov bx, buffer
add bx, cx
mov [bx], al
inc cx
jmp end
back_space:
cmp cx, 0x00
je end
dec cx
mov ah, 0x0e
mov al, 0x08
int 0x10
mov al, 0x20
int 0x10
mov al, 0x08
int 0x10
jmp end
enter:
xor cx, cx
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
call pro_com
call clear_buffer
mov ah, 0x0e
mov al, '>'
int 0x10
end:
ret

str_prt:
pusha
str:
mov ah, 0x0e
mov al, [bx]
cmp al, '$'
je str_end
int 0x10
add bx, 1
jmp str
str_end:
popa
ret

new_line:
push ax
mov ah, 0x0e
mov al, 0x0a
int 0x10
mov al, 0x0d
int 0x10
pop ax
ret

clear_buffer:
push ax
push bx
push cx
mov bx, buffer
xor cx, cx
xor ax, ax
start:
cmp cx, 0x41
je end_buff
mov [bx], ax
inc bx
inc cx
jmp start
end_buff:
pop cx
pop bx
pop ax
ret

pro_com:
push bx
push ax
mov bx, buffer
mov al, [bx]
cmp al, 'h'
jne help_end
inc bx
mov al, [bx]
cmp al, 'e'
jne help_end
inc bx
mov al, [bx]
cmp al, 'l'
jne help_end
inc bx
mov al, [bx]
cmp al, 'p'
jne help_end
call com_help
jmp pro_end
help_end:
mov bx, buffer
mov al, [bx]
cmp al, 'd'
jne dir_end
inc bx
mov al, [bx]
cmp al, 'i'
jne dir_end
inc bx
mov al, [bx]
cmp al, 'r'
jne dir_end
call com_dir
jmp pro_end
dir_end:
mov bx, not_found
call str_prt
call new_line
pro_end:
pop ax
pop bx
ret

com_help:
push bx
call new_line
mov bx, help1_msg
call str_prt
call new_line
call new_line
pop bx
ret

com_dir:
push ax
push bx
push cx
push dx
mov bx, drive_num
mov dl, [bx]
mov cl, 0x09
mov al, 0x01
mov ch, 0x00
mov cl, 0x09
mov dh, 0x00
com_dir_loop:
call read_dir
cmp cl, 0x12
je false1
inc cx
jmp com_dir_loop
false1:
pop dx
pop cx
pop bx
pop ax 
ret

read_dir:
push ax
push bx
mov bx, 0x1000
mov es, bx
mov bx, 0xe00
call read_disc
clc
mov bx, 0x0e00
mov al, [bx]
cmp al, 'F'
jne read_dir_end
;print file name
mov bx, 0x0e01
call str_prt
call new_line
;----
read_dir_end:
pop bx
pop ax 
mov bx, 0x1000
mov es, bx
ret

read_disc:
mov ah, 0x02   
int 0x13   
ret

buffer times 20 db 0

drive_num:
db 0


welcome_msg:
db 'Welcome to matriXos$'
creator_msg:
db 'Created by Vishnu Shankar.B$'
boot_msg:
db 'Booting command line interface...$'
not_found:
db 'Command cannot be resolved!$'
help1_msg:
db 'Help not avilable!$'


jmp $
times 3584 - ($ - $$) db 0




命令"dir"(com_dir)应该读取并打印以字母"F"开头的字符串,如果每个扇区9-18(轨道0)(CHS),则字母"F"开始.我已经使用十六进制编辑器将字符串放在适当的位置.
我将代码转换为图像文件.它在Bochs模拟器中工作正常,但是当我在闪存驱动器上刻录图像文件并在我的计算机中启动它时,它会打印垃圾.
谁能告诉我有什么问题?
提前致谢.



1> Michael Petc..:

在我之前的回答中,我碰巧删除了引导加载程序中将DL设置为零的行.你的bootloader这样做了:

mov dl,0x0  ;Drive = 0 (Floppy)

这需要删除.我现在已经在我之前的回答中给出了这个评论的原因:

这硬盘将引导驱动器编码到软盘A:.如果您从USB,硬盘驱动器或软盘B启动:您的代码将无法运行,因为在这些情况下驱动器号可能不会为零.BIOS传递用于加载引导加载程序的实际引导驱动器.该值在寄存器DL中.这是您应该用于BIOS磁盘功能的值.由于DL已包含启动驱动器,因此我们只是按原样使用它.

重用传递给引导加载程序的DL中的值以进行驱动器读取和写入,但也将此值传递给第二阶段!由于您的引导加载程序实际上不会破坏DL的内容,因此您只需将DL移动到您的drive_num变量中即可.您可以在第二阶段设置DS寄存器后立即执行此操作,如下所示:

[BITS 16]
[ORG 0x0000]

mov ax, cs
mov ds, ax
mov [drive_num], dl    ; drive_num = the boot drive the BIOS booted from

如果您修改了引导加载程序以便它破坏DXDL寄存器的内容,那么您应该考虑在引导加载程序启动后将其推入堆栈,然后在跳转到第二个之前将其弹出(恢复它)阶段.

在我之前的回答中提到的引导程序中,我这样开始:

xor ax, ax
mov ds, ax        ; DS=0

cli               ; Turn off interrupts for SS:SP update
                  ; to avoid a problem with buggy 8088 CPUs
mov ss, ax        ; SS = 0x0000
mov sp, 0x7c00    ; SP = 0x7c00
                  ; We'll set the stack starting just below
                  ; where the bootloader is at 0x0:0x7c00. The
                  ; stack can be placed anywhere in usable and
                  ; unused RAM.
sti               ; Turn interrupts back on

设置堆栈后,我们可以通过以下方式保存DX寄存器:

xor ax, ax
mov ds, ax        ; DS=0

cli               ; Turn off interrupts for SS:SP update
                  ; to avoid a problem with buggy 8088 CPUs
mov ss, ax        ; SS = 0x0000
mov sp, 0x7c00    ; SP = 0x7c00
                  ; We'll set the stack starting just below
                  ; where the bootloader is at 0x0:0x7c00. The
                  ; stack can be placed anywhere in usable and
                  ; unused RAM.
sti               ; Turn interrupts back on
push dx           ; Save DX register (which includes DL) on stack

现在它被保存了,我们可以在跳到第二阶段之前恢复它的值.这段代码:

jmp 0x1000:0000   ; Jump to 0x1000, start of second stage

现在这样做:

pop dx            ; Restore DX register (which includes DL)
jmp 0x1000:0000   ; Jump to 0x1000, start of second stage

这有效地将DL(引导驱动器)传递到我们的第二阶段,即使在我们可能在执行引导加载程序期间破坏其内容的情况下也是如此.然后,我们的第二阶段能够重用该值来进行自己的BIOS磁盘读写操作.

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有