【问题标题】:A boot loader in C++C++ 中的引导加载程序
【发布时间】:2010-07-17 21:53:17
【问题描述】:

我在软盘上制作了一个小型程序集引导加载程序,并想知道是否可以在 C++ 中制作引导加载程序,如果可以,我可以从哪里开始?据我所知,我不确定它是否会使用int main()

感谢您的帮助。

【问题讨论】:

  • 我相信是有区别的。这个问我应该如何进行,另一个是关于 C 和 C++ 之间的选择。但有一些重叠。

标签: c++ assembly bootloader


【解决方案1】:

如果您正在编写引导加载程序,那么您实际上是从无到有:一小段代码被加载到内存中并被执行。您可以用 C++ 编写大部分引导加载程序,但您需要先引导自己的 C++ 运行时环境。

Assembly 确实是第一阶段的唯一选择,因为您需要设置一个合理的环境来运行任何更高级别的东西。做足够多的事情来运行 C 代码是相当简单的——你需要:

  • 代码和数据加载在正确的位置;
  • 数据区域中可能有一个附加部分必须进行零初始化;
  • 您需要将堆栈指针指向堆栈的合适内存区域。

然后您可以在适当的位置(例如main())跳转到代码,并期望基本的语言 功能能够正常工作。 (可能已经实现或链接的标准的任何功能都可能需要在此阶段进行额外的初始化。)

获得一个适合 C++ 的环境需要更多的努力,因为它需要更多的初始化,并且还具有需要运行时支持的核心语言特性(同样,这是在考虑库特性之前)。其中包括:

  • 运行静态构造函数;
  • 内存分配支持newdelete
  • 支持运行时类型信息 (RTTI);
  • 支持异常;
  • 可能还有其他一些我忘记提及的事情。

在 C 环境启动并运行之前,这些都不是必需的,因此处理这些的代码可以用 C 而不是汇编器编写(甚至可以用不使用上述特性的 C++ 子集编写)。

(相同的原则适用于嵌入式系统,此类系统使用 C++ 的情况并不少见,但仅以有限的方式使用——例如,没有例外和/或 RTTI,因为未实现运行时支持。)

【讨论】:

    【解决方案2】:

    我已经有一段时间没有玩写引导加载程序了,所以我要记忆犹新了。

    对于 x86 引导加载程序,您需要有一个可以发出 x86 程序集的 C++ 编译器,或者,至少,您需要在 16 位程序集中编写自己的前导码,将 CPU 置于 32 位保护状态(或 64 位长)模式,然后才能调用 C++ 函数。

    不过,一旦你这样做了,你应该能够使用 C++ 的大部分(如果不是全部)语言特性,只要你远离需要底层 libc 的东西。但是没有 CRT 的情况下静态链接所有东西,你就是金子。

    【讨论】:

      【解决方案3】:

      引导加载程序没有“int main()”,除非您编写汇编代码来调用它。 如果您正在编写阶段 1 引导加载程序,那么非常不鼓励这样做。

      否则,osdev.org 有关于该主题的大量文档。
      虽然可能在 C++ 中创建引导加载程序,但请记住不要将您的代码链接到任何动态库,并记住仅仅因为它是 C++,这并不意味着您可以/应该使用STL等

      【讨论】:

      • 如果是C++,可以使用STL。这就是故事的结局。如果你不能使用 STL,那就不是 C++。
      • 有尾巴就是狗,没有尾巴就不是狗
      • @DeadMG 你不可能是认真的。 STL 是一种 API,而不是语言。这是一个引导加载程序。时期。这意味着没有“新”/“删除”关键字,除非您明确定义它们,没有文件 I/O,除非您明确定义自己的文件函数。换句话说,除非您静态链接专门为这些目的设计的标准库,或者编写您自己的 STL,否则您将无法使用 STL 中的几乎任何东西。而且,无论哪种方式,使用它都可能是个坏主意。
      • @luiscubal:如果你用 C++ 编译,你的编译器有义务为你提供一个新的/删除的实现。我不会争论你是否应该这样做。但是,这些是 C++ 生活中的事实,那些实现和那些头文件是 C++ 编译器的强制性要求。如果您可以为“bootloader”环境编译 C++,那么编译器的工作就是解决上述问题并为您提供 STL 以供使用。在引导加载程序环境中实现 STL 的技术困难不是所述编译器用户的问题——它们只是使这种情况不太可能存在。
      • @DeadMG new/delete 是 malloc/calloc/free 的 C++ 等价物。如果没有 malloc/calloc/free,您如何期望 C++ 为您提供这些?除非您编写自己的 new/delete 运算符实现,否则引导加载程序 C++ 中没有 new/delete。
      【解决方案4】:

      是的,这是可能的。 this question中有答案元素和有用的链接

      你也可以看看here,有一个C++ bootloader例子。

      要了解的主要内容是,您需要创建一个平面二进制文件而不是通常花哨的可执行文件格式(Windows 上的 PE,或 Unix 上的 ELF),因为这些文件格式需要操作系统来加载它们,并且在您还没有操作系统的引导加载程序。

      如果您静态链接,使用库不是问题(没有动态链接,因为上述可执行问题再次出现)。但显然所有与 OS API 相关的入口点都不可用...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-10-03
        • 1970-01-01
        • 2011-10-28
        • 2010-12-10
        • 2021-04-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多