“中断10h”未显示字符串

时间:2014-05-18 15:48:44

标签: assembly operating-system x86 interrupt bootloader

在VMWare和Bochs上运行操作系统引导加载程序时遇到问题。

引导加载程序应该通过int 10h显示一个字符串,但它只打印没有任何字符的背景颜色。

颜色由bx的值设定。代码在这里:

    org 7c00h
;   org 0100h
    mov ax, cs
    mov ds, ax
    mov es, ax
    call  DispStr
    jmp $

DispStr:
    mov ax, BootMessage
    mov bp, ax
    mov cx, 13
    mov ax, 1301h
    mov bx, 005eh
    mov dh, 3
    mov dl, 0
    int 10h
    ret

BootMessage:        db "Hello, Luser!"
times 510-($-$$)    db 0

dw  0xaa55

1 个答案:

答案 0 :(得分:1)

虽然这个答案很晚,但问题很简单,代码是开发人员的一个很好的例子,假设BIOS跳转到具有有效或预期值的代码。我最近回答了一些关于 bootloaders 的问题,并开始提供general tips。提示#1应适用于此处:

  1. 当BIOS跳转到您的代码时,您不能依赖 CS DS ES SS SP 寄存器具有有效或预期的值。应该在启动引导程序启动时正确设置它们。
  2. 由于您正在进行BIOS int调用,因此应确保设置自己的堆栈。您不能保证 SS / SP 指向足够的堆栈空间,或者当BIOS跳转到物理内存地址0x00007C00的代码时甚至有效。唯一的要求是BIOS开始在该位置执行代码,但它没有说明应该使用 CS IP 来执行此操作。 BIOS还将通过DL中的启动驱动器。

    许多不同的segment:offset对可以引用单个物理内存位置。例如,这些都指向引导加载程序物理地址:

    0x0000:0x7C00 = (0x0000<<4)+0x7C00 = 0x00007C00
    0x0203:0x5BD0 = (0x0203<<4)+0x5BD0 = 0x00007C00
    0x07C0:0x0000 = (0x07C0<<4)+0x0000 = 0x00007C00 
    

    正如您所看到的,上面的示例让您了解使用segment:offset对解决单个内存位置的方法不止一种。海报提供的代码假定 CS 段将为0。可以观察代码中的org 7c00h,它表示当编译器生成目标文件时,所有绝对近存储器引用都会被0x7C00偏移。由于我们将在0x7C00内存加载到内存中,因此我们的 DS 必须为0x000

    这与OP的代码有何关系。注意我们从:

    开始
    mov ax, cs
    mov ds, ax
    mov es, ax
    

    我们盲目地移动 CS 中的内容并将其传输到 DS ES 。我们的代码特别需要0x0000 DS 才能正常工作(来源0x7C00)。我给出了一些映射到物理位置0x7C00 CS:IP 对的示例。如果BIOS专门通过远程跳转跳转到我们的代码0x0000:0x7C00,我们的 CS 将是0x0000 IP 将是0x7C00。如果我们将0x0000移至 DS ES ,一切都会好的。如果BIOS 远远跳转到0x07C0:0x0000会发生什么?我们的 CS 中包含0x07C0 IP 将为0x0000。如果我们将 CS 移动到 ES DS ,所有这些段都是0x07C0,但我们编写的代码相对于{{{ 1}}。

    错误的段可能会出错?假设汇编程序将0x0000置于偏移Bootmessage(0x50 + 0x7C00原点)。现在执行以下代码:

    0x7C50

    由于没有指定任何段,因此它与说mov ax, BootMessage 相同。如果我们的 DS 段设置为DS:BootMessage0x07C0设置为Bootmessage,那么我们就会访问物理地址(0x07C0&lt;&lt;&lt; 4)+ 0x7C50 = { {1}}。现在应该很明显 - 如果 CS 不是0,我们将从我们的字符串不存在的内存地址加载 BootMessage

    要解决这个问题很简单。不要认为 CS 是我们所期望的。对引导加载程序进行编码以使用我们想要的内容。我们打算将 DS ES 设置为细分0x7C50

    0xF850

    使用0x0000和其他一些使用xor ax, ax ; Set AX to 0 mov ds, ax ; Initialize DS=ES=0 mov es, ax 的其他人知道远jmp 到我们的引导加载程序的一些虚拟机和真实硬件。如果您认为 CS 中的值是您想要的,那么您的代码可能在某些平台上运行,而不是在其他平台上运行。