在 QEmu 中使用简单引导扇区从磁盘读取不正确的字节
Incorrect Bytes Being Read from disk using a Simple Boot sector, in QEmu
所以我正在尝试学习如何制作一些 OS,主要是使用 this 教程。
我在该教程的第 28 页,正在尝试使用小型磁盘加载程序。
然而,当我 运行 qemu-system-i386 boot_sector.bin
,它适用于前面的引导扇区示例时,我得到的十六进制输出是 0xDADA 0xZRWV
,其中第一个是正确的,而第二个不是。
我的代码如下
Boot_sector.asm
; Very simple boot sector to read sectors from disk
jmp main ; ensures that we start where we want to
%include "disk_load.asm"
BOOT_DRIVE:
db 0
[org 0x7c00] ; tell the assembler where this code will be loaded
main:
mov bp, 0x8000 ; Make sure the stack is out of our way
mov sp, bp
mov bx, 0x9000
mov dh, 2 ; Want to read 2 sectors
call disk_load
mov dx, [0x9000]
call hex_print ; Should output 0xDADA
mov dx, [0x9000 + 512]; Should output 0xFACE
call hex_print
hang:
jmp hang ; Continually jump to current location
; Add padding and magic BIOS number (to let BIOS know this is a boot sector)
times 510-($-$$) db 0 ; pad with zeroes
dw 0xaa55 ; magic number
times 256 dw 0xdada ; second sector
times 256 dw 0xface ; third sector
disk_load.asm:
%include "bios_print.asm"
ERROR_MSG:
db "Disk read error!", 0
SECTOR_ERROR_MSG:
db "Wrong number of sectors read!", 0
disk_load:
push dx ; Store the number of sectors we wanted to read
mov ah, 0x02 ; BIOS read sector function
mov al, dh ; Number of sectors to be read
mov ch, 0x00 ; Cylinder 0
mov dh, 0x00 ; Head 0
mov cl, 0x02 ; Sector 2 (just after the boot sector)
int 0x13
jc disk_error ; if carry flag is set, report an error
pop dx
cmp dh, al
jne sector_error ; if we didn't read as many sectors as we wanted.
ret
disk_error:
mov bx, ERROR_MSG
call bios_print
jmp $
sector_error:
mov bx, SECTOR_ERROR_MSG
call bios_print
jmp $
然后bios_print.asm只有打印十六进制等的功能:
bios_print:
pusha
mov si, bx
loop:
lodsb
or al, al
jz done
mov ah, 0x0e
int 0x10
jmp loop
done:
popa
ret
HEX_OUT:
db '0x0000', 0
hex_print:
pusha
mov cx, 4 ; Counter
char_loop:
dec cx
mov ax, dx
shr dx, 4
and ax, 0xf ; Mask to get the last part of ax
mov bx, HEX_OUT
add bx, 2 ; Skip the '0x' in HEX_OUT
add bx, cx
; If the character is a number, we just plop that out, but if it
; is a letter, we have to convert it to ASCII by adding 7 (because
; ASCII starts at 17, and the numbers end at 10)
cmp ax, 0xa
jl set_char
add byte [bx], 7
jl set_char
set_char:
add byte [bx], al ; Add the value of the byte to the char stored at bx
cmp cx, 0
je finished
jmp char_loop
finished:
mov bx, HEX_OUT
call bios_print
popa
ret
我也尝试过 运行使用 -fda 标志来连接 QEmu,这在一些地方被建议,但没有成功。此外,如果我将要读取的扇区数更改为 5(如教程中所示),我会收到驱动器读取错误(由 disk_load 函数引发)。
这让我很生气。在此先感谢您的帮助。
-_- 我刚刚弄清楚问题出在哪里。
调用 hex_print
后,我没有重置 HEX_STRING
。
我通过简单地将 HEX_STRING
的位置复制回 BX,然后遍历 BX,间接将 HEX_STRING
的每个字节设置为 ASCII 0 来修复此问题。
这已解决问题。
所以我正在尝试学习如何制作一些 OS,主要是使用 this 教程。
我在该教程的第 28 页,正在尝试使用小型磁盘加载程序。
然而,当我 运行 qemu-system-i386 boot_sector.bin
,它适用于前面的引导扇区示例时,我得到的十六进制输出是 0xDADA 0xZRWV
,其中第一个是正确的,而第二个不是。
我的代码如下
Boot_sector.asm
; Very simple boot sector to read sectors from disk
jmp main ; ensures that we start where we want to
%include "disk_load.asm"
BOOT_DRIVE:
db 0
[org 0x7c00] ; tell the assembler where this code will be loaded
main:
mov bp, 0x8000 ; Make sure the stack is out of our way
mov sp, bp
mov bx, 0x9000
mov dh, 2 ; Want to read 2 sectors
call disk_load
mov dx, [0x9000]
call hex_print ; Should output 0xDADA
mov dx, [0x9000 + 512]; Should output 0xFACE
call hex_print
hang:
jmp hang ; Continually jump to current location
; Add padding and magic BIOS number (to let BIOS know this is a boot sector)
times 510-($-$$) db 0 ; pad with zeroes
dw 0xaa55 ; magic number
times 256 dw 0xdada ; second sector
times 256 dw 0xface ; third sector
disk_load.asm:
%include "bios_print.asm"
ERROR_MSG:
db "Disk read error!", 0
SECTOR_ERROR_MSG:
db "Wrong number of sectors read!", 0
disk_load:
push dx ; Store the number of sectors we wanted to read
mov ah, 0x02 ; BIOS read sector function
mov al, dh ; Number of sectors to be read
mov ch, 0x00 ; Cylinder 0
mov dh, 0x00 ; Head 0
mov cl, 0x02 ; Sector 2 (just after the boot sector)
int 0x13
jc disk_error ; if carry flag is set, report an error
pop dx
cmp dh, al
jne sector_error ; if we didn't read as many sectors as we wanted.
ret
disk_error:
mov bx, ERROR_MSG
call bios_print
jmp $
sector_error:
mov bx, SECTOR_ERROR_MSG
call bios_print
jmp $
然后bios_print.asm只有打印十六进制等的功能:
bios_print:
pusha
mov si, bx
loop:
lodsb
or al, al
jz done
mov ah, 0x0e
int 0x10
jmp loop
done:
popa
ret
HEX_OUT:
db '0x0000', 0
hex_print:
pusha
mov cx, 4 ; Counter
char_loop:
dec cx
mov ax, dx
shr dx, 4
and ax, 0xf ; Mask to get the last part of ax
mov bx, HEX_OUT
add bx, 2 ; Skip the '0x' in HEX_OUT
add bx, cx
; If the character is a number, we just plop that out, but if it
; is a letter, we have to convert it to ASCII by adding 7 (because
; ASCII starts at 17, and the numbers end at 10)
cmp ax, 0xa
jl set_char
add byte [bx], 7
jl set_char
set_char:
add byte [bx], al ; Add the value of the byte to the char stored at bx
cmp cx, 0
je finished
jmp char_loop
finished:
mov bx, HEX_OUT
call bios_print
popa
ret
我也尝试过 运行使用 -fda 标志来连接 QEmu,这在一些地方被建议,但没有成功。此外,如果我将要读取的扇区数更改为 5(如教程中所示),我会收到驱动器读取错误(由 disk_load 函数引发)。
这让我很生气。在此先感谢您的帮助。
-_- 我刚刚弄清楚问题出在哪里。
调用 hex_print
后,我没有重置 HEX_STRING
。
我通过简单地将 HEX_STRING
的位置复制回 BX,然后遍历 BX,间接将 HEX_STRING
的每个字节设置为 ASCII 0 来修复此问题。
这已解决问题。