我知道这是一个很难回答的问题,主要是因为有很多事情可能是错误的,很难确定。但我会提供尽可能多的信息;希望这会有所帮助。
我开始使用 D 语言和 Digital Mars D 编译器编写自己的内核,在弄清楚如何生成可以重定位的平面二进制文件后遇到了很多麻烦,我终于想出了生成一个普通 PE 文件的想法地址,并用字节(NOP 操作码)0xC0000000
替换其所有标头。0x90
这工作得非常好,我可以在屏幕上写东西,设置分页,进入保护模式等等。当然,借助 16 位基于汇编的引导加载程序的帮助。
一切都很好,也就是说,我决定移植 D 运行时库以在我的内核中使用。我设法提取了该库的一个子集并对其进行了修改以将其编译到我的应用程序中。然后我运行我的程序。(注意:我根本没有 使用该库;我的代码是启动后执行的第一个代码——发生的第一件事是打印"Kernel"
到屏幕上,在此之前没有调用任何运行时代码。)
AD 数组(因此是字符串,因为字符串只是 a char[]
)只不过是一个具有指针和大小成员的结构,因此在 32 位系统上它将是 8 个字节大。有趣的是,当我运行我的程序时,结构的成员显示为零——也就是说,指针和大小都为零。(我通过在屏幕上打印指针的值以及长度成员来验证这一点——两者都为零。)一旦我删除了运行时的源代码(无论如何都没有执行),它们工作得很好.
我将其缩小为两种可能性:
堆栈不知何故设置不正确:我排除了这一点,因为没有运行时库一切正常,我通过反汇编文件确认在我的代码之前没有执行其他代码。
PE 文件部分有些有趣:我检查并发现运行时版本中有两个 TLS(线程本地)变量。果然,当我让它们共享(而不是线程本地)时,我的代码工作了!但是,当我调用我在不同文件中编写的代码时,我的代码仍然表现出同样
kernel.d
的问题——只有作为启动文件的代码在使用字符串时表现正确;在其他文件中,数组再次为零。
现在,有没有人猜测为什么会发生这种情况?
如果需要更多信息,我很乐意发布。
谢谢!