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

ioekq8ef  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(96)

我在VMWare和Bochs上运行操作系统 Boot 加载程序时遇到问题。
Boot 加载程序应该通过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

字符串

3phpmpom

3phpmpom1#

虽然这个答案很晚,但问题很简单,代码是一个很好的例子,说明开发人员假设BIOS跳转到具有有效或预期值的代码。我最近回答了一些关于 * bootloader * 的问题,并开始提供一般提示。Tip#1应该适用于这里:
1.当BIOS跳转到您的代码时,您不能依赖具有有效或预期值的 CSDSESSSSP 寄存器。它们应该在启动 Bootstrap 时进行适当的设置。
由于您正在进行BIOS int调用,因此应确保设置自己的堆栈。当BIOS跳转到物理内存地址0x00007C00的代码时,您不能保证 SS/SP 指向足够的堆栈空间,甚至不能保证它有效。唯一的要求是BIOS在该位置开始执行您的代码,但它没有说明应该使用什么 CSIP 来执行。BIOS还将通过DL中的 Boot 驱动器。
单个物理内存位置可以被许多不同的segment:offset对引用。例如,这些都指向 Boot 加载程序的物理地址:

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 中的内容并将其转移到 DSES。我们的代码特别需要一个0x0000DS 才能正常工作(origin为0x7C00)。我给出了一些Map到物理位置0x7C00CS:IP 对的示例。如果BIOS跳到我们的代码,特别是 * 远跳 * 到0x0000:0x7C00,我们的 CS 将是0x0000IP 将是0x7C00。如果我们把0x0000移到 DSES,一切都会很好。如果BIOS * 跳到 * 0x 07 C 0:0x 0000,会发生什么?我们的 CS 中有0x07C0IP 中有0x0000。如果我们将 CS 移到 ESDS,所有这些段都是0x07C0,但我们编写的代码是相对于0x0000的段的。
如果使用错误的片段,会出现什么问题?假设Bootmessage被汇编程序放置在偏移量0x7C50(0x 50 + 0x 7 C 00原点)处。现在执行以下代码:

mov ax, BootMessage


由于没有指定任何段,因此它将与DS:BootMessage相同。如果我们的 DS 段被设置为0x07C0Bootmessage被设置为0x7C50,那么我们正在访问物理地址(0x 07 C 0 <<4)+0x7C50 = 0xF850。现在应该很明显-如果 CS 不为0,我们正在从一个不存在字符串的内存地址加载 BootMessage
解决这个问题很简单。不要假设 CS 是我们所期望的。编写引导加载程序以使用我们想要的。我们打算将 DSES 设置为段0x0000

xor ax, ax      ; Set AX to 0
mov ds, ax      ; Initialize DS=ES=0
mov es, ax


一些虚拟机和真实的硬件可以使用0x07C0:0x0000far jmp 到我们的引导加载程序,而另一些则使用0x0000:0x7C00。如果你假设 CS 中的值是你想要的,那么你的代码可能在某些平台上工作,而不是其他平台。

zbwhf8kr

zbwhf8kr2#

在你的台词里:

mov ax, BootMessage
 mov bp, ax

字符串
我不相信可以像这里一样直接将地址移动到AX,因为在x86中没有可用的指令来查询AX寄存器本身的地址指针。
相反,为什么不直接将其移动到BX中,如下所示:

mov BX, BootMessage
  ; and move the byte pointed to by [BX] into AL for 0x10 video ops
  mov al, [BX]


不知道这是不是已经试过了??

相关问题