【问题标题】:ASM int 0x10 stops working after jumping to second sectorASM int 0x10 跳转到第二个扇区后停止工作
【发布时间】: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


【解决方案1】:

正如 Jester 在他的评论中指出的那样,除了为 ORG 使用了错误的值之外,您还使用 0023h 的值(光标的初始值)加载了 DS。相反,您应该使用存储在 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

...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多