D中的我的OS内核:某些嵌入式字符串不起作用

Meh*_*dad 7 boot kernel d portable-executable bootloader

我知道这是一个相当难以回答的问题,主要是因为有很多事情可能是错误的,很难把事情搞得一团糟.但我会尽可能多地提供信息; 希望这会有所帮助.

我开始使用D语言和Digital Mars D编译器编写自己的内核,并且在弄清楚如何生成可以重新定位的平面二进制文件之后遇到了很多麻烦,我终于提出了生成普通PE文件的想法.地址0xC0000000,并用字节0x90(NOP操作码)替换所有标头.这非常好用,我能够在屏幕上编写内容,设置分页,完全进入保护模式等,当然还有16位基于汇编的引导加载程序的帮助.

一切都很顺利,也就是说,我决定将D运行时库移植到我的内核中.我设法提取了库的一个子集并对其进行修改以使其编译到我的应用程序中.然后我运行了我的程序.(注意:我根本没有 使用该库;我的代码是在引导后执行的第一个代码 - 第一件事就是打印"Kernel"到屏幕上,之前没有调用运行时代码.)

AD数组(因此字符串,因为字符串只是一个char[])只不过是一个带有指针和大小成员的结构,因此在32位系统上它将是8字节大.有趣的是,当我运行我的程序时,结构的成员显示为零 - 也就是说,指针和大小都为零.(我通过将指针的值打印到屏幕以及长度成员来验证这一点 - 两者都是零.)一旦我删除了运行时的源代码(从未执行过),它们工作正常.

我把它缩小到两种可能性:

  1. 堆栈在某种程度上没有正确设置:我排除了这一点,因为没有运行时库,一切正常,我确认在我的代码之前没有通过反汇编文件执行其他代码.

  2. PE文件部分很有趣:我检查过,并发现在运行时版本中有两个TLS(线程局部)变量.果然,当我让它们共享(而不是线程本地)时,我的代码工作了!但是,当我调用我在不同文件中编写的代码时,我的代码仍然会出现同样的问题 - 只有kernel.d启动文件才能正确处理字符串; 在其他文件中,数组再次为零.

现在,有没有人猜到为什么会发生这种情况?

如果需要更多信息,我很乐意发布.

谢谢!

asv*_*kau 6

首先,免责声明:我不知道关于D的第一件事.

第二,另一个免责声明:基于使用术语"PE文件"我会猜测你正在使用Windows.我即将给出一个GNU工具链的建议......

但是......假设D编译器生成目标文件就像其他任何一样......为什么不执行以下操作(这是我在C中使用业余爱好操作系统时所做的,当我有时间做这些事情时):

  • 为您的内核生成ELF二进制文件...为此,请正常构建所有目标文件.在链接步骤中,将链接器脚本提供给ld它将定义诸如起始地址,二进制的部分(文本,数据,rodata等)的顺序......
  • 使用GRUB启动它(相当容易...你需要在二进制文件的开头附近添加一些神奇的单词.你可以在.asm文件中执行此操作dbdw键入语句,前提是相应的obj最终在开头附近链接的内核.看看这个链接)

通过这种方式,您可以专注于更多有趣的事情,而不是破解PE头或编写引导程序.

当然......完全有可能代码本身存在一些问题,而不是你链接的方式.在某些可以让您逐步完成程序集输出的内容中运行它可能会提供信息.x86 PC仿真器qemu有一些调试选项,可以将汇编和寄存器状态输出到日志.我以前用过它.


Meh*_*dad 1

一年之后...

\n

解决了!:D

\n

(> '.')> \xc2\xa0 (^'.'^) \xc2\xa0 <('.' )> \xc2\xa0 (v'.'v) \xc2\xa0 <('.' < )

\n

这是我的引导加载程序的问题:我读入内存的扇区太少。(即 64 个扇区,而不是128 125 个。)

\n