【发布时间】:2016-03-22 22:38:30
【问题描述】:
我正在尝试为 x86 机器创建一个小型操作系统,并开始为一个相当小的引导加载程序编写代码。我创建的引导加载程序非常简单,它从直接位于主引导记录之后的扇区加载一个小的第二个引导加载程序并跳转到该代码。主引导记录中的引导加载程序代码似乎运行良好,当它尝试跳转到第二阶段引导加载程序时出现问题。这个第二阶段的引导加载程序应该输出一个表示成功的字母(字母 S),所以我可以知道代码正在执行。问题是屏幕上什么都没有出现,所以我怀疑第二阶段引导加载程序从未执行过。我使用的代码如下:
主引导记录中的引导加载程序:
[BITS 16] ; 16 bit mode
[ORG 0x7C00] ; Boot loader start address
Boot:
; Initial, dl contains drive number
; Set data segment to code segment
mov ax, cs
mov ds, ax
mov es, ax
; Set the stack segment to 0xA000
add ax, 0xA000
mov ss, ax
mov sp, 0x00
; Reset the drive, dl contains drive number
mov ah, 0x00
int 0x13
; Read from drive, dl contains drive number
; Set up output location to 0x7E00: 0x00
mov ax, 0x7E00
mov es, ax ; Load to 0x7E00 : 0x00
mov bx, 0x00
ReadDrive:
mov ah, 0x02
mov al, 0x01 ; Read 1 sector
mov ch, 0x00 ; Read on cylinder 0
mov cl, 0x02 ; Read sector 2
mov dh, 0x00 ; Head number 0
int 0x13
jnc Success
; Print error (character F)
mov al, 0x46
call PrintChar
jmp ReadDrive ; Retry
PrintChar: ; Prints a single character
pusha
mov ah, 0x09
mov bh, 0x00
mov bl, 0x0F
mov cx, 0x01
int 0x10
popa
ret
Success:
jmp 0x7E00:0x00 ; Jump to 2nd stage bootloader
TIMES 510 - ($ - $$) db 0
DW 0xAA55 ; Boot signature
第二阶段bootloader的代码:
[BITS 16]
[ORG 0x7E00]
Boot2:
; Prints the character S to the screen
mov al, 0x53
mov ah, 0x09
mov bh, 0x00
mov bl, 0x0F
mov cx, 0x01
int 0x10
jmp $ ; Loop forever
TIMES 512 - ($ - $$) db 0 ; Fill rest of block
此代码是使用以下代码编译并写入驱动器的:
nasm boot.asm -o boot.bin -f bin
nasm boot2.asm -o boot2.bin -f bin
dd if=boot.bin of=/dev/sd3 bs=512
dd if=boot2.bin of=/dev/sd3 bs=512 seek=1
写入此代码的设备是 16GB USB 驱动器。我用来启动此代码的计算机支持从 USB 启动并像任何其他硬盘驱动器一样启动它们。代码似乎没有执行的原因是什么?
【问题讨论】:
-
如果你在第二阶段的顶部使用
[ORG 0x0000],并且第一行代码用mov ax, csmov ds, ax初始化DS会发生什么? -
如何知道引导扇区运行成功?
-
第二个也是最重要的,你跳转到
jmp 0x7E00:0x00。这是物理地址 (0x7e00jmp 0x07E0:0x00,即 (0x07e0 -
您确定第一阶段运行正常吗?也许它应该输出一个字符来确定。在这种环境下,您确定
dl有驱动器号吗? -
当您开始定义数据变量并尝试在第二阶段使用它们时,我的第一条评论的重要性将变得显而易见。如果没有正确设置 DS,所有对变量的引用都将位于错误的偏移量。您的代码目前没有变量,因此您不会注意到问题。如果您远 jmp 到第二阶段,ORG 指令应该等于跳转到的偏移量。如果您在上面进行了建议的 jmp 更改 (
jmp 0x07E0:0x00),那么 JMP 会将 CS:IP 更改为 CS=0x07E0, IP=0x0000 。您希望 ORG 等于 IP。所以 ORG 应该是 0x0000。
标签: assembly x86 nasm bootloader real-mode