【发布时间】:2015-07-19 23:56:09
【问题描述】:
我正在尝试了解操作系统的工作原理,因此我正在编写一些基本代码以在模拟软盘驱动器的引导扇区上运行。当我运行代码时,存储在软盘第一个扇区中的代码按预期执行;它打印字符串:“Loading floppy”,但是当它加载下一段代码时,它不会打印字符串“Sector 2 loaded”,它只是将光标甩动(这是预期的行为)。我正在使用 Oracle VirtualBox 来模拟一个带有软盘驱动器的系统,以及一个十六进制编辑器来将我的二进制文件组合成一个由 NASM 编译的单个 .img 文件。为了使每一位代码清楚地表明它的作用,代码被过多地注释并且效率低下。 这是代码
引导扇区(0x0000-0x01FF):
org 0x7C00 ;Tell compiler that this is where code starts
bits 16 ;The CPU is in Real 16bit mode
jmp Start ;Skip over the string stored at the top of the program
Msg: db "Loading the floppy ... "
EndMsg:
Start:
mov bl, 0x0F ;Set text colour to 15
mov bh, 0x00 ;Set page to 0
mov cx, 0x001 ;Set number of characters to 1
xor dx, dx ;Set x and y to 0
mov ds, dx ;Allow for message loading
cld ;Allow for message loading
Print:
mov si, Msg ;Load the pointer Msg into si
Char:
mov ah, 0x02 ;Set the sub-function to 2
int 0x10 ;Call function 0x10 - position cursor
lodsb ;load the byte at si into al
mov ah, 0x09 ;Set the sub-function to 9
int 0x10 ;Call function 0x10 - print character
inc dl ;Advance the cursor
cmp dl, 80 ;If the cursor is past column 80
jne Skip ;Else jump to Skip
xor dl,dl ;reset the cursor's x value
inc dh ;move the cursor down a row
cmp dh, 25 ;If the cursor is past line 25
jne Skip ;Else jump to Skip
xor dh,dh ;move the cursor to the top row
Skip:
cmp si, EndMsg ;If the message is finished
jne Char ;Else print another character
ResetDisk:
mov ah, 0x00 ;Reset sub-function
mov dl, 0x00 ;Drive declaration
int 0x13 ;Disk function, sub 0 - Reset disk
jc ResetDisk ;If this fails, try again
ReadDisk:
mov bx, 0x8000 ;Where in RAM to drop the read data
mov es, bx
mov bx, 0x0000 ;RAM offset value
mov ah, 0x02 ;Set sub-function
mov al, 0x01 ;Set the number of sectors to read
mov ch, 0x00 ;Set the cylinder to read
mov cl, 0x02 ;Set the sector to start at (begins at 1, rest start at 0)
mov dh, 0x00 ;Set the drive head to read from
mov dl, 0x00 ;Set which drive to read from
int 0x13 ;Disk function, sub 2 - Read disk as described above
jc ReadDisk
AdvanceToSectorTwo:
jmp 0x8000:0x0000 ;Jump to the location of the second sector
times 0x0200 - 2 - ($ - $$) db 0 ;Fill the rest of the first sector up to byte 510
dw 0xAA55 ;Set bytes 511 and 512 to be the boot-disk signature
times 1474560 - ($ - $$) db 0 ;Fill up the rest of the floppy image as blank space
Sector-2(0x0200-0x3FF):
org 0x8000
bits 16
Start:
mov bl, 0x0F ;Set text colour to 15
mov bh, 0x00 ;Set page to 0
mov cx, 0x001 ;Set number of characters to 1
mov dl, 23 ;Set column
mov dh, 0 ;Set Row
mov ds, dx ;Allow for message loading
cld ;Allow for message loading
Print:
mov si, Msg ;Load the pointer Msg into si
Char:
mov ah, 0x02 ;Set the sub-function to 2
int 0x10 ;Call function 0x10 - position cursor
lodsb ;load the byte at si into al
mov ah, 0x09 ;Set the sub-function to 9
int 0x10 ;Call function 0x10 - print character
inc dl ;Advance the cursor
cmp dl, 80 ;If the cursor is past column 80
jne Skip ;Else jump to Skip
xor dl,dl ;reset the cursor's x value
inc dh ;move the cursor down a row
cmp dh, 25 ;If the cursor is past line 25
jne Skip ;Else jump to Skip
xor dh,dh ;move the cursor to the top row
Skip:
cmp si, EndMsg ;If the message is finished
jne Char ;Else print another character
jmp Start ;Restart this part of the program
Msg: db "floppy sector 2 loaded!"
EndMsg:
很抱歉,这太长了。同样,它可以很好地打印第一个字符串,但它拒绝打印第二个字符串,它只是移动光标。非常感谢任何建议。
【问题讨论】:
-
一方面,您将代码加载到 segment
0x8000但使用org 0x8000即段0x800。修复一个或另一个。另外,学习使用调试器。 PS:此外,你使用jmp 0x8000:0x0000,它使用偏移量0,所以你真的想要org 0。
标签: assembly x86 operating-system bootloader