4

我一直在研究实模式操作系统,用 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(;;);
}

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

4

2 回答 2

4

您使用了错误的地址。

您可以在 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 函数,而您在启动程序时没有这些函数。在此处查看如何解决此问题。
于 2012-03-24T20:56:20.703 回答
1

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

于 2012-03-24T19:58:25.863 回答