第二扇区不能加载到引导文件中

发布于 2025-02-04 07:22:33 字数 4670 浏览 2 评论 0原文

这是一小部分引导加载程序的代码的一部分。
它仅显示“ 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦在深巷 2025-02-11 07:22:33

主要问题:您正在将80h单元用于从启动加载单元加载,但是将图像作为磁盘驱动器传递给QEMU,因此您应该使用00h单元。

解决方案:保留dl寄存器(dx的一部分),就像进入装载机时一样。先前的加载程序将当前的启动加载单元传递给您在此寄存器中,因此只需使用它即可。


其他nitpicks:

  • 没有错误处理,失败时会崩溃。

  • 堆栈应由您的代码设置,以避免可能干扰您的扇区负载。

  • 完成运行后,您应该使某种无限的循环结束,而不是让执行继续超过代码末尾。我围绕sti \ hlt进行循环。

  • 您列出的完整源有另一个错误,它缺少开头的Square Bracket [ BITS指令。 (这似乎是由NASM允许的。

  • 您没有在构建脚本中安装任何东西,因此您不需要扎根。

  • 您目前不需要创建ISO映像,也没有使用它来运行您的程序。

  • ,如果您只是覆盖前两个扇区,则无需创建DOS文件系统,这使文件系统无法使用。我用另一个dd命令。


这是我的固定脚本和源,除了仍然丢失的错误处理和堆栈设置。脚本:

#!/bin/sh

if [ ! -e disk_images/os.flp ]
then
  echo ">>> Creating new OS floppy image..."
  dd if=/dev/zero of=disk_images/os.flp bs=1024 count=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 '>>> Done!'

源:(注意按下dxpop dxsti \ hlt hlt loop。)

[   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

push dx

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
pop dx
; 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

haltloop:
sti
hlt
jmp haltloop

statement db "ok", 0

; add how much memory we need
times (1024 - ($-$)) db 0x00

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 of dx) 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 the bits 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 the bits 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:

#!/bin/sh

if [ ! -e disk_images/os.flp ]
then
  echo ">>> Creating new OS floppy image..."
  dd if=/dev/zero of=disk_images/os.flp bs=1024 count=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 '>>> Done!'

Source: (Note the push dx, pop dx, and sti \ hlt loop.)

[   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

push dx

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
pop dx
; 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

haltloop:
sti
hlt
jmp haltloop

statement db "ok", 0

; add how much memory we need
times (1024 - ($-$)) db 0x00
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文