16-bit .com C program in real mode OS

I'm working on a real mode OS, writing build and compile to flat .bin binaries from NASM.
I would like to write some of the OSes in C, and so I wrote an experimental program (ctest.c) that I would like to access the string and print the first character:

void test();

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

char msg [] = "Hello World!";

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


I have compiled this with Open Watcom v1.9 with wcl ctest.c -lr -l=COM

. This creates ctest.com. The kernel I wrote in the NASM build loads this program at 0x2010: 0x0000, sets DS and ES to 0x2000: 0x0000, then jumps to 0x2010: 0x0000. This is how I called .COM programs written in assembly and compiled with nasm -f bin test.asm -o test.com

When I test the OS (using Bochs) it loads ctest.com successfully but prints a meaningless character that is not part of msg [].
Anyone have any suggestions on this? I think the string is just being initialized in the wrong place. I would like to save this as a 16 bit OS.


source to share

2 answers

You are using the wrong addresses.

You either boot from 0x2000: 0x0100 and go to 0x2000: 0x0100 (remember to set DS = ES = SS = 0x2000 and SP = 0 before that) OR you boot 0x2000: 0x0000 (equivalent to 0x1FF0: 0x0100 because 0x2000 * 0x10 + 0x0000 = 0x1FF0 * 0x10 + 0x0100 = 0x20000 = real mode physical memory address) and go to 0x1FF0: 0x0100 (remember to set DS = ES = SS = 0x1FF0 and SP = 0 before that).

The reason for all of this is that compiled x86 code is generally not position independent, and if you move it, you must adjust some data offsets within the code. Obviously, you haven't made these adjustments. In simple cases, you had nothing to correct and you left with the wrong addresses.


In fact, there are more problems here:

  • mov si, word ptr [msg]

    should change to lea si, byte ptr [msg]

    because you don't want to load si

    with what is inside a string, you want to load it with a string address.
  • The startup code associated with your OW program is DOS dependent and calls DOS functions that you do not have when you boot your program. See how to get around this here .


In MS-DOS, COM programs were loaded at offset 0x100. I would guess Open Watcom makes this assumption. I would suggest loading the COM program at 0x2010: 0x0100 and see what it does.



All Articles