我一直在研究一个真正的模式操作系统,用汇编编写并使用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。这就是我一直在调用汇编编写的.COM程序,并用nasm -f bin test.asm -o test.com
编译
当我测试操作系统(使用Bochs)时,它成功加载ctest.com,但打印出一个无意义的字符,该字符不属于msg []。
有人对此有任何建议吗?我认为字符串只是在错误的地方初始化。我想将其保留为16位操作系统
谢谢!
答案 0 :(得分:4)
您使用的是错误的地址。
你要么加载到0x2000:0x0100并跳转到0x2000:0x0100(不要忘记在此之前设置DS = ES = SS = 0x2000和SP = 0) OR 你加载到0x2000: 0x0000(相当于0x1FF0:0x0100因为0x2000 * 0x10 + 0x0000 = 0x1FF0 * 0x10 + 0x0100 = 0x20000 =实模式下的物理存储器地址)并跳转到0x1FF0:0x0100(不要忘记设置DS = ES = SS = 0x1FF0和SP之前= 0)。
所有这一切的原因是编译的x86代码通常不是与位置无关的,如果你移动它,你必须调整代码内部的一些数据偏移。显然,你没有做出这些调整。在简单的情况下,没有什么可以调整的,你就得错了地址。
修改强>:
实际上,这里存在更多问题:
mov si, word ptr [msg]
必须更改为lea si, byte ptr [msg]
,因为您不想加载si
字符串中的内容,而是希望使用字符串的地址加载它。答案 1 :(得分:1)
在MS-DOS下,COM程序在偏移量0x100处加载。我猜想Open Watcom会做出这样的假设。我建议加载COM程序在0x2010:0x0100,看看它做了什么。