第二扇区不能加载到引导文件中
这是一小部分引导加载程序的代码的一部分。
它仅显示“ myos”,但不显示“确定”。
. . .
mov si, statement1
call print_string
; load second sector into memory
mov ah, 0x02 ; load second stage to memory
mov al, 1 ; numbers of sectors to read into memory
mov dl, 0x80 ; sector read from fixed/usb disk
mov ch, 0 ; cylinder number
mov dh, 0 ; head number
mov cl, 2 ; sector number
mov bx, _OS_Stage_2 ; load into es:bx segment :offset of buffer
int 0x13 ; disk I/O interrupt
jmp _OS_Stage_2 ; jump to second stage
. . .
statement1 db "myos", 0
; boot loader magic number
times ((0x200 - 2) - ($ - $$)) db 0x00 ;set 512 bytes for boot sector which are necessary
dw 0xAA55 ; boot signature 0xAA & 0x55
_OS_Stage_2:
. . .
mov si, statement2
call print_string
statement2 db "ok", 0
; add how much memory we need
times (1024 - ($-$$)) db 0x00
这是跳到 _OS_STAGE_2 的代码。它不起作用。
此处包含完整的源代码,
bits 16] ; tell assembler that working in real mode(16 bit mode)
[org 0x7c00] ; organize from 0x7C00 memory location where BIOS will load us
start: ; start label from where our code starts
xor ax,ax ; set ax register to 0
mov ds,ax ; set data segment(ds) to 0
mov es,ax ; set extra segment(es) to 0
mov bx,0x8000
mov ax,0x13 ;clears the screen
int 0x10 ;call bios video interrupt
mov ah,02 ;clear the screen with big font
int 0x10 ;interrupt displayt
; cursor position
mov al, 2
mov ah, 0
mov bl, 4
mov bh, 0
int 0x10
mov si, command_prompt
call print_string
mov ax,0x00 ; get keyboard input
int 0x16 ; interrupt for hold & read input
; load second sector into memory
mov ah, 0x02 ; load second stage to memory
mov al, 1 ; numbers of sectors to read into memory
mov dl, 0x80 ; sector read from fixed/usb disk
mov ch, 0 ; cylinder number
mov dh, 0 ; head number
mov cl, 2 ; sector number
mov bx, _OS_Stage_2 ; load into es:bx segment :offset of buffer
int 0x13 ; disk I/O interrupt
jmp _OS_Stage_2 ; jump to second stage
int 0x19
print_string:
mov ah, 0x0E ; value to tell interrupt handler that take value from al & print it
.repeat_next_char:
lodsb ; get character from string
cmp al, 0 ; cmp al with end of string
je .done_print ; if char is zero, end of string
int 0x10 ; otherwise, print it
jmp .repeat_next_char ; jmp to .repeat_next_char if not 0
.done_print:
ret ;return
command_prompt db "myos", 0
; boot loader magic number
times ((0x200 - 2) - ($ - $$)) db 0x00 ;set 512 bytes for boot sector which are necessary
dw 0xAA55 ; boot signature 0xAA & 0x55
_OS_Stage_2:
mov al,2 ; set font to normal mode
mov ah,0 ; clear the screen
int 0x10 ; call video interrupt
mov si, statement
call print_string
statement db "ok", 0
; add how much memory we need
times (1024 - ($-$$)) db 0x00
上述代码由NASM组装,如下所示,由QEMU模拟器在Ubuntu中由./build-linux.sh(file)组装。
#!/bin/sh
if test "`whoami`" != "root"
then
echo "You must be logged in as root to build (for loopback mounting)"
echo "Enter 'su' or 'sudo bash' to switch to root"
exit
fi
if [ ! -e disk_images/os.flp ] then
echo ">>> Creating new OS floppy image..."
mkdosfs -C disk_images/os.flp 1440 || exit
fi
echo ">>> Assembling bootloader..."
nasm -O0 -w+orphan-labels -f bin -o source/bootload/nasma/boot.bin source/bootload/nasma/boot.asm || exit
echo ">>> Adding bootloader to floppy image..."
dd status=noxfer conv=notrunc if=source/bootload/nasma/boot.bin of=disk_images/os.flp || exit
echo ">>> Creating CD-ROM ISO image..."
rm -f disk_images/os.iso
mkisofs -quiet -V 'OS' -input-charset iso8859-1 -o disk_images/os.iso -b os.flp disk_images/ || exit
echo '>>> Done!'
Test-Linux(文件)运行该程序如下
#!/bin/sh
qemu-system-i386 -soundhw pcspk -drive format=raw,file=disk_images/os.flp,index=0,if=floppy
This is a part of the code of a small sample of bootloader.
It displays "myos" ONLY, but does not display "ok".
. . .
mov si, statement1
call print_string
; load second sector into memory
mov ah, 0x02 ; load second stage to memory
mov al, 1 ; numbers of sectors to read into memory
mov dl, 0x80 ; sector read from fixed/usb disk
mov ch, 0 ; cylinder number
mov dh, 0 ; head number
mov cl, 2 ; sector number
mov bx, _OS_Stage_2 ; load into es:bx segment :offset of buffer
int 0x13 ; disk I/O interrupt
jmp _OS_Stage_2 ; jump to second stage
. . .
statement1 db "myos", 0
; boot loader magic number
times ((0x200 - 2) - ($ - $)) db 0x00 ;set 512 bytes for boot sector which are necessary
dw 0xAA55 ; boot signature 0xAA & 0x55
_OS_Stage_2:
. . .
mov si, statement2
call print_string
statement2 db "ok", 0
; add how much memory we need
times (1024 - ($-$)) db 0x00
Here is the code to jump to _OS_Stage_2. It does not work.
THE FULL SOURCE CODE IS INCLUDED HERE
bits 16] ; tell assembler that working in real mode(16 bit mode)
[org 0x7c00] ; organize from 0x7C00 memory location where BIOS will load us
start: ; start label from where our code starts
xor ax,ax ; set ax register to 0
mov ds,ax ; set data segment(ds) to 0
mov es,ax ; set extra segment(es) to 0
mov bx,0x8000
mov ax,0x13 ;clears the screen
int 0x10 ;call bios video interrupt
mov ah,02 ;clear the screen with big font
int 0x10 ;interrupt displayt
; cursor position
mov al, 2
mov ah, 0
mov bl, 4
mov bh, 0
int 0x10
mov si, command_prompt
call print_string
mov ax,0x00 ; get keyboard input
int 0x16 ; interrupt for hold & read input
; load second sector into memory
mov ah, 0x02 ; load second stage to memory
mov al, 1 ; numbers of sectors to read into memory
mov dl, 0x80 ; sector read from fixed/usb disk
mov ch, 0 ; cylinder number
mov dh, 0 ; head number
mov cl, 2 ; sector number
mov bx, _OS_Stage_2 ; load into es:bx segment :offset of buffer
int 0x13 ; disk I/O interrupt
jmp _OS_Stage_2 ; jump to second stage
int 0x19
print_string:
mov ah, 0x0E ; value to tell interrupt handler that take value from al & print it
.repeat_next_char:
lodsb ; get character from string
cmp al, 0 ; cmp al with end of string
je .done_print ; if char is zero, end of string
int 0x10 ; otherwise, print it
jmp .repeat_next_char ; jmp to .repeat_next_char if not 0
.done_print:
ret ;return
command_prompt db "myos", 0
; boot loader magic number
times ((0x200 - 2) - ($ - $)) db 0x00 ;set 512 bytes for boot sector which are necessary
dw 0xAA55 ; boot signature 0xAA & 0x55
_OS_Stage_2:
mov al,2 ; set font to normal mode
mov ah,0 ; clear the screen
int 0x10 ; call video interrupt
mov si, statement
call print_string
statement db "ok", 0
; add how much memory we need
times (1024 - ($-$)) db 0x00
The above code is assembled by NASM as below by ./build-linux.sh (file) in ubuntu with qemu emulator.
#!/bin/sh
if test "`whoami`" != "root"
then
echo "You must be logged in as root to build (for loopback mounting)"
echo "Enter 'su' or 'sudo bash' to switch to root"
exit
fi
if [ ! -e disk_images/os.flp ] then
echo ">>> Creating new OS floppy image..."
mkdosfs -C disk_images/os.flp 1440 || exit
fi
echo ">>> Assembling bootloader..."
nasm -O0 -w+orphan-labels -f bin -o source/bootload/nasma/boot.bin source/bootload/nasma/boot.asm || exit
echo ">>> Adding bootloader to floppy image..."
dd status=noxfer conv=notrunc if=source/bootload/nasma/boot.bin of=disk_images/os.flp || exit
echo ">>> Creating CD-ROM ISO image..."
rm -f disk_images/os.iso
mkisofs -quiet -V 'OS' -input-charset iso8859-1 -o disk_images/os.iso -b os.flp disk_images/ || exit
echo '>>> Done!'
The test-linux (file) runs the program as below
#!/bin/sh
qemu-system-i386 -soundhw pcspk -drive format=raw,file=disk_images/os.flp,index=0,if=floppy
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
主要问题:您正在将80h单元用于从启动加载单元加载,但是将图像作为磁盘驱动器传递给QEMU,因此您应该使用00h单元。
解决方案:保留
dl
寄存器(dx
的一部分),就像进入装载机时一样。先前的加载程序将当前的启动加载单元传递给您在此寄存器中,因此只需使用它即可。其他nitpicks:
没有错误处理,失败时会崩溃。
堆栈应由您的代码设置,以避免可能干扰您的扇区负载。
完成运行后,您应该使某种无限的循环结束,而不是让执行继续超过代码末尾。我围绕
sti
\hlt
进行循环。您列出的完整源有另一个错误,它缺少开头的Square Bracket
[
BITS
指令。 (这似乎是由NASM允许的。您没有在构建脚本中安装任何东西,因此您不需要扎根。
您目前不需要创建ISO映像,也没有使用它来运行您的程序。
,如果您只是覆盖前两个扇区,则无需创建DOS文件系统,这使文件系统无法使用。我用另一个
dd
命令。这是我的固定脚本和源,除了仍然丢失的错误处理和堆栈设置。脚本:
源:(注意
按下dx
,pop dx
和sti
\ hlt hlt loop。)Main problem: You're hardcoding unit 80h for loading from your boot load unit, but you're passing the image as a diskette drive to qemu so you should use unit 00h.
Solution: Preserve the
dl
register (part ofdx
) as it was upon entry to your loader. The prior loader passes the current boot load unit to you in this register so just use that.Additional nitpicks:
No error handling, it just crashes when failing.
Stack should be set up by your code to avoid possibly interfering with your sector load.
After you finished running you should make some sort of infinite loop to end, rather than letting execution continue past the end of your code. I made a loop around
sti
\hlt
to save power.The full source you listed has another mistake, it is missing the opening square bracket
[
for thebits
directive. (This appears to be allowed by NASM but it is wrong.) Dropping the closing square bracket is also valid, there are two forms of thebits
directive either with or without the brackets.You aren't mounting anything in your build script so you don't need to be root.
You don't need to create an ISO image at this point and did not use it to run your program in fact.
You don't need to create a DOS filesystem if you're just overwriting the first two sectors anyway, which makes the filesystem unusable. I replaced this with another
dd
command.Here's my fixed script and source, except for the error handling and stack setup which is still missing. Script:
Source: (Note the
push dx
,pop dx
, andsti
\hlt
loop.)