如何解决磁盘读取功能无法在Bootloader中按预期方式工作
我正在尝试开发基本的引导加载程序,但是当我尝试创建用于从硬盘驱动器读取其他扇区的功能时遇到了一个问题。我正在NASM的Kali Linux上开发它,并使用QEMU作为仿真器。 这是我的主要引导程序文件:
[org 0x7c00]
mov bp,0x8000
mov sp,bp
call read_disk
mov si,my_string
call print ;prints a string,si points to the string to be printed
jmp $
read_disk
mov ah,0x02 ;read from disk
mov al,0x01 ;read one sector
mov ch,0x00 ;read from cylinder 0
mov dh,0x00 ;read from head 0
mov cl,0x02 ;read the second sector
mov bx,0
mov es,bx
mov bx,0x7c00+512
int 0x13
jc disk_error ;BIOS sets the carry flag if disk read was unsuccessful
ret
disk_error:
mov si,error_msg
call print
jmp $
;
;Functions
;
%include "functions/print.asm"
%include "functions/print_hex.asm"
%include "functions/print_nl.asm"
%include "functions/calc_len.asm"
%include "functions/find_string.asm"
;
;Data
;
error_msg:
db 'Error reading disk',0
times 510-($-$$) db 0 ;pad out the rest of the bootloader with zeros to increase the size to 512 bytes
dw 0xaa55 ;Magic bytes so BIOS recognizes the hard drive as bootable
;
;SECOND SECTOR
;
my_string:
db 'Disk read successful',0
times 512 db 0 ;need to pad out the rest of the sector with zeros since QEMU requires it
如您所见,my_string
位于512字节之后,位于仿真硬盘驱动器的第二个扇区中。但是,当我编译并运行引导加载程序时,它不会输出任何内容。在上面提供的代码中,我在my_string
函数结束之后打印read_disk
。但奇怪的是,如果我将打印my_string
的两个行移到函数的内部,它将起作用。
这是有效的代码:
[org 0x7c00]
mov bp,bp
call read_disk
jmp $
read_disk
mov ah,0x7c00+512
int 0x13
jc disk_error ;BIOS sets the carry flag if disk read was unsuccessful
mov si,my_string
call print ;prints a string,si points to the string to be printed
ret
disk_error:
mov si,0
times 512 db 0 ;need to pad out the rest of the sector with zeros since QEMU requires it
如果有人能向我解释这种奇怪的怪诞,我将不胜感激。
解决方法
在读取内存之前,您应该设置 SS:SP 而不只是将其设置为 SP 。 SS 可以为零,也可以不为零。如果 SS 恰好是0x0000,则您的堆栈位于0x0000:0x8000处,并且将从此处向下生长。
您的代码将磁盘上的第二个512字节扇区读入内存,地址为0x0000:0x7e00,其中包括直到{x1fee}函数返回地址的所有字节,并包括位于堆栈中0x0000:0x7ffe的函数的返回地址。到0x0000:0x7fff。
由于破坏了堆栈,disk_read
可能永远不会返回,因为内部数据,返回地址和标志已损坏。像这样破坏堆栈将导致无法预料的结果。考虑将堆栈放在引导加载程序下方的0x0000:0x7c00处,以免干扰在引导加载程序之后加载的数据和代码。
注意:您应该将所需的所有段寄存器设置为期望的值。您不应依赖任何包含特定值的段寄存器。 BIOS不保证其值,尽管在大多数仿真器中它们将为0x0000。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。