跳转到第二个扇区后,ASM int 0x10停止工作

时间:2015-05-08 23:50:22

标签: assembly x86 operating-system bootloader

我正在尝试了解操作系统的工作原理,因此我正在制作一些基本代码,以便在模拟软盘驱动器的bootsector上运行。当我运行代码时,存储在软盘的第一个扇区中的代码按预期执行;它打印字符串:“加载软盘”,但是当它加载下一段代码时,它不会打印字符串“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

扇区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:

很抱歉这太久了。再次,它打印第一个字符串就好了,但第二个它拒绝打印,它只是移动光标。任何建议都非常感谢。

1 个答案:

答案 0 :(得分:0)

除了使用错误的ORG值之外,正如Jester在评论中指出的那样,您还要加载DS,其值为0023h,即光标的初始值。相反,您应该使用存储在CS中的值加载DS,这样您的第二个扇区就不会关心它加载到哪个网段。例如:

org 0
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
    push cs
    pop ds
    cld             ;Allow for message loading

...