简体   繁体   English

实模式OS中的16位.com C程序

[英]16-bit .com C program in real mode OS

I've been working on a real mode OS, writing in assembly and compiling to flat .bin executables with NASM. 我一直在研究一个真正的模式操作系统,用汇编编写并使用NASM编译成扁平的.bin可执行文件。
I would like to write some of the OS in C, and so wrote an experiment program (ctest.c) which I would like to access a string and print the first character: 我想用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(;;);
}

I compiled this with Open Watcom v1.9 using wcl ctest.c -lr -l=COM . 我使用wcl ctest.c -lr -l=COM在Open Watcom v1.9中编译了这个。 This creates ctest.com. 这创建了ctest.com。 The kernel, which I wrote in NASM assembly, loads this program to 0x2010:0x0000, sets DS and ES to 0x2000:0x0000 and then jumps to 0x2010:0x0000. 我在NASM程序集中编写的内核将此程序加载到0x2010:0x0000,将DS和ES设置为0x2000:0x0000,然后跳转到0x2010:0x0000。 This is how I have been calling .COM programs written in assembly and compiled with nasm -f bin test.asm -o test.com . 这就是我一直在调用汇编编写的.COM程序,并使用nasm -f bin test.asm -o test.com编译。
When I test the OS (using Bochs), it successfully loads ctest.com, but prints out a meaningless character that is not part of msg[]. 当我测试操作系统(使用Bochs)时,它成功加载ctest.com,但打印出一个无意义的字符,该字符不属于msg []。
Does anyone have any suggestions about this? 有人对此有任何建议吗? I think the string is just being initialized in the wrong place. 我认为字符串只是在错误的地方初始化。 I would like to keep this as a 16-bit OS. 我想将其保留为16位操作系统。
thanks! 谢谢!

You are using wrong addresses. 您使用的是错误的地址。

You either load at 0x2000:0x0100 and jump to 0x2000:0x0100 (don't forget setting DS=ES=SS=0x2000 and SP=0 prior to that) OR you load at 0x2000:0x0000 (equivalent to 0x1FF0:0x0100 because 0x2000*0x10+0x0000 = 0x1FF0*0x10+0x0100 = 0x20000 = physical memory address in real mode) and jump to 0x1FF0:0x0100 (don't forget setting DS=ES=SS=0x1FF0 and SP=0 prior to that). 你要么加载到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)。

The reason for all of this is that compiled x86 code is generally not position-independent and if you move it, you have to adjust some data offsets inside of the code. 所有这一切的原因是编译的x86代码通常不是位置独立的,如果你移动它,你必须调整代码内部的一些数据偏移。 Obviously, you weren't making these adjustments. 显然,你没有做出这些调整。 In simple cases there was nothing to adjust and you got away with wrong addresses. 在简单的情况下,没有什么可以调整,你得到了错误的地址。

EDIT : 编辑

Actually, there're more problems here: 实际上,这里有更多的问题:

  1. mov si, word ptr [msg] must change to lea si, byte ptr [msg] because you don't want to load si with what's inside the string, you want to load it with the string's address. mov si, word ptr [msg]必须更改为lea si, byte ptr [msg]因为你不想用字符串里面的内容加载si ,你想用字符串的地址加载它。
  2. The startup code that's linked to your program by OW is dependent on DOS and calls DOS functions, which you don't have when you boot your program. 由OW链接到您的程序的启动代码依赖于DOS并调用DOS函数,这是您在启动程序时没有的。 See how to work around this here . 看看如何解决这个问题

Under MS-DOS, COM programs were loaded at offset 0x100. 在MS-DOS下,COM程序在偏移0x100处加载。 I would guess that Open Watcom makes that assumption. 我猜想Open Watcom会做出这样的假设。 I would suggest loading the COM program at 0x2010:0x0100 and see what that does. 我建议加载COM程序在0x2010:0x0100,看看它做了什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM