磁盘读取功能在引导加载程序中未按预期工作
Disk Read Function not Working as Expected in 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
函数结束后打印。但是 st运行gely 足够了,如果我将打印 my_string
的两行移动到 函数中,它就可以工作。
这是有效的代码:
[org 0x7c00]
mov bp, 0x8000
mov sp, bp
call read_disk
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
mov si, my_string
call print ;prints a string, si points to the string to be printed
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
如果有人能向我解释这个 st运行ge 奇怪之处,我将不胜感激。
在读入内存之前,您应该设置 SS:SP 而不仅仅是 SP。 SS 可能为零,也可能不是。如果 SS 恰好是 0x0000 那么你的堆栈在 0x0000:0x8000 并且它会从那里向下增长。
您的代码将磁盘上的第二个 512 字节扇区读取到位于 0x0000:0x7e00 的内存中,其中包括所有字节直至并包括 disk_read
函数的 return 地址放在堆栈上 0x0000:0x7ffe 到 0x0000:0x7fff.
由于您破坏了堆栈,int 0x13
可能永远不会 return 因为内部数据、return 地址和标志已损坏。像这样破坏堆栈将产生不可预知的结果。考虑将堆栈 0x0000:0x7c00 放在引导加载程序下方,以免干扰您在引导加载程序之后加载的数据和代码。
注意:您应该将您需要的所有段寄存器设置为您期望的值。您不应该依赖任何包含特定值的段寄存器。 BIOS 不保证它们的值,尽管在大多数模拟器中它们将是 0x0000。
我正在尝试开发一个基本的引导加载程序,但是当我尝试创建一个从硬盘驱动器读取额外扇区的函数时,我 运行 遇到了问题。我正在 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
函数结束后打印。但是 st运行gely 足够了,如果我将打印 my_string
的两行移动到 函数中,它就可以工作。
这是有效的代码:
[org 0x7c00]
mov bp, 0x8000
mov sp, bp
call read_disk
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
mov si, my_string
call print ;prints a string, si points to the string to be printed
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
如果有人能向我解释这个 st运行ge 奇怪之处,我将不胜感激。
在读入内存之前,您应该设置 SS:SP 而不仅仅是 SP。 SS 可能为零,也可能不是。如果 SS 恰好是 0x0000 那么你的堆栈在 0x0000:0x8000 并且它会从那里向下增长。
您的代码将磁盘上的第二个 512 字节扇区读取到位于 0x0000:0x7e00 的内存中,其中包括所有字节直至并包括 disk_read
函数的 return 地址放在堆栈上 0x0000:0x7ffe 到 0x0000:0x7fff.
由于您破坏了堆栈,int 0x13
可能永远不会 return 因为内部数据、return 地址和标志已损坏。像这样破坏堆栈将产生不可预知的结果。考虑将堆栈 0x0000:0x7c00 放在引导加载程序下方,以免干扰您在引导加载程序之后加载的数据和代码。
注意:您应该将您需要的所有段寄存器设置为您期望的值。您不应该依赖任何包含特定值的段寄存器。 BIOS 不保证它们的值,尽管在大多数模拟器中它们将是 0x0000。