【问题标题】:16-bit .com C program in real mode OS实模式操作系统中的 16 位 .com C 程序
【发布时间】:2012-03-24 19:48:35
【问题描述】:

我一直在研究实模式操作系统,用汇编编写并使用 NASM 编译成平面 .bin 可执行文件。
我想用C写一些操作系统,所以写了一个实验程序(ctest.c),我想访问一个字符串并打印第一个字符:

void test();

int main() { test(); return 0; }

char msg [] = "Hello World!";

void test() {
    _asm
    {
        mov si, word ptr [msg]
        mov al, [si]
        mov ah, 0eh
        int 10h
    }
    for(;;);
}

我使用 wcl ctest.c -lr -l=COM 使用 Open Watcom v1.9 编译了这个。这将创建 ctest.com。我在 NASM 汇编中编写的内核将这个程序加载到 0x2010:0x0000,将 DS 和 ES 设置为 0x2000:0x0000,然后跳转到 0x2010:0x0000。这就是我一直在调用用汇编编写并使用nasm -f bin test.asm -o test.com 编译的.COM 程序的方式。
当我测试操作系统(使用 Bochs)时,它成功加载了 ctest.com,但打印出一个不属于 msg[] 的无意义字符。
有人对此有什么建议吗?我认为字符串只是在错误的地方初始化。我想将其保留为 16 位操作系统。
谢谢!

【问题讨论】:

  • .com 内存映像的前 128 个字节包含操作系统数据,类似于 CP/M。 DOS 依赖于它。接下来的 128 个字节包含命令行。执行从 0x100 开始。

标签: c assembly x86 bootloader watcom


【解决方案1】:

您使用了错误的地址。

您可以在 0x2000:0x0100 加载并跳转到 0x2000:0x0100(不要忘记在此之前设置 DS=ES=SS=0x2000 和 SP=0)或者您在 0x2000 加载: 0x0000 (相当于 0x1FF0:0x0100 因为 0x2000*0x10+0x0000 = 0x1FF0*0x10+0x0100 = 0x20000 = 实模式下的物理内存地址)并跳转到 0x1FF0:0x0100 (不要忘记设置 DS=ES=SS=0x1FF0 和 SP =0 之前)。

所有这些的原因是编译的 x86 代码通常不是位置无关的,如果你移动它,你必须调整代码内部的一些数据偏移量。显然,您没有进行这些调整。在简单的情况下,没有什么可调整的,而您却使用了错误的地址。

编辑

其实这里还有很多问题:

  1. mov si, word ptr [msg] 必须更改为 lea si, byte ptr [msg],因为您不想使用字符串中的内容加载 si,而是希望使用字符串的地址加载它。
  2. OW 链接到您的程序的启动代码依赖于 DOS 并调用 DOS 函数,而您在启动程序时没有这些函数。了解如何解决此问题here

【讨论】:

    【解决方案2】:

    在 MS-DOS 下,COM 程序在偏移量 0x100 处加载。我猜 Open Watcom 会做出这样的假设。我建议在 0x2010:0x0100 加载 COM 程序,看看会发生什么。

    【讨论】:

    • 我刚试过,但没有用。顺便说一句,我正在使用 int 13h ah 2 从虚拟软盘上读取扇区。
    猜你喜欢
    • 2017-02-02
    • 2017-07-17
    • 2023-01-25
    • 1970-01-01
    • 2013-10-31
    • 2011-07-29
    • 2015-09-26
    • 1970-01-01
    • 2013-09-08
    相关资源
    最近更新 更多