如何为基于 ROM 的程序预初始化内存数据结构?
How can in-memory data structures be pre-initialized for ROM-based programs?
考虑 STL unordered_map
。相同的模板 class 用于在运行时生成的哈希表,以及由编译时常量值组成的哈希表。虽然最近版本的 C++ 添加了 constexpr
支持,但它没有扩展到涉及自由存储的更复杂的操作,因此从编译时常量构建哈希表仍然必须在运行时发生,这使得它与构建任何其他的一样昂贵运行时的哈希表。
理想情况下,一个完美的编译器会看到这一点并在编译时预先评估哈希表构造并将其直接嵌入到程序中。
这让我想到了逆向计算和微控制器,考虑到汇编的开发成本,可以想象它们的软件是用 C 或 C++ 编写的:这些环境通常有有限的 RAM 但有大量的 ROM,以及那些内存中的数据结构(例如 unordered_map
) 当然可以在编译时预先生成并保存到 ROM。
如前所述,C++ 语言不支持非平凡 constexpr
。我知道你可以一起破解这个假设你可以将复杂的数据结构基于数组类型或将其减少到 constexpr
- 或者将它们全部写在汇编中并手动将结构的每个字节设置为十六进制-editor 并希望它与编译器对您的 struct
类型的表示相匹配(例如)。
那今天是怎么做的呢?在 RAM 和 CPU 周期非常宝贵的 16 位和 32 位游戏机时代,它是如何实现的?我特别热衷于了解基于 ROM 卡带的游戏,其中的结构可以作为原始内存立即访问。
unordered_map
是一种非常低效的数据结构类型,您永远不会在那种设置中使用它。更合理的事情,如数组和树,使用静态初始化器很容易做到。如果它变得更复杂,您可以编写一个程序来生成包含所需静态初始值设定项的 C,并 运行 在可以处理它的系统上。
在 C++ 微控制器系统中,所有具有静态存储持续时间的对象的构造函数在启动期间被调用,在 .data
和 .bss
等段被初始化的点附近,在 main() 之前叫。这是 C++ 往往不适合此类系统的几个原因之一——它实际上在启动阶段执行应用程序代码。
你提到的那种应用程序,比如老式视频游戏,很可能有预先计算好的表格并用 ROM 编写。我怀疑 C++ 是否在此类游戏中被大量使用,或者如果是,它们使用了该语言的一个受限子集。
回到“Ye Olden Days”- 80 年代和 90 年代初期,RAM 非常昂贵,闪存既昂贵又不可靠,但是 ROM,尤其是掩码 ROM 很便宜。
视频游戏机通常使用少量 RAM 作为“暂存器”内存从 ROM 执行游戏。例如,原始的 NES 控制台有 2048 字节的 RAM
游戏开发中未使用编译语言,因此为了回答您最初的问题,数据结构已初始化,将一个空结构从 ROM 复制到 RAM
考虑 STL unordered_map
。相同的模板 class 用于在运行时生成的哈希表,以及由编译时常量值组成的哈希表。虽然最近版本的 C++ 添加了 constexpr
支持,但它没有扩展到涉及自由存储的更复杂的操作,因此从编译时常量构建哈希表仍然必须在运行时发生,这使得它与构建任何其他的一样昂贵运行时的哈希表。
理想情况下,一个完美的编译器会看到这一点并在编译时预先评估哈希表构造并将其直接嵌入到程序中。
这让我想到了逆向计算和微控制器,考虑到汇编的开发成本,可以想象它们的软件是用 C 或 C++ 编写的:这些环境通常有有限的 RAM 但有大量的 ROM,以及那些内存中的数据结构(例如 unordered_map
) 当然可以在编译时预先生成并保存到 ROM。
如前所述,C++ 语言不支持非平凡 constexpr
。我知道你可以一起破解这个假设你可以将复杂的数据结构基于数组类型或将其减少到 constexpr
- 或者将它们全部写在汇编中并手动将结构的每个字节设置为十六进制-editor 并希望它与编译器对您的 struct
类型的表示相匹配(例如)。
那今天是怎么做的呢?在 RAM 和 CPU 周期非常宝贵的 16 位和 32 位游戏机时代,它是如何实现的?我特别热衷于了解基于 ROM 卡带的游戏,其中的结构可以作为原始内存立即访问。
unordered_map
是一种非常低效的数据结构类型,您永远不会在那种设置中使用它。更合理的事情,如数组和树,使用静态初始化器很容易做到。如果它变得更复杂,您可以编写一个程序来生成包含所需静态初始值设定项的 C,并 运行 在可以处理它的系统上。
在 C++ 微控制器系统中,所有具有静态存储持续时间的对象的构造函数在启动期间被调用,在 .data
和 .bss
等段被初始化的点附近,在 main() 之前叫。这是 C++ 往往不适合此类系统的几个原因之一——它实际上在启动阶段执行应用程序代码。
你提到的那种应用程序,比如老式视频游戏,很可能有预先计算好的表格并用 ROM 编写。我怀疑 C++ 是否在此类游戏中被大量使用,或者如果是,它们使用了该语言的一个受限子集。
回到“Ye Olden Days”- 80 年代和 90 年代初期,RAM 非常昂贵,闪存既昂贵又不可靠,但是 ROM,尤其是掩码 ROM 很便宜。
视频游戏机通常使用少量 RAM 作为“暂存器”内存从 ROM 执行游戏。例如,原始的 NES 控制台有 2048 字节的 RAM
游戏开发中未使用编译语言,因此为了回答您最初的问题,数据结构已初始化,将一个空结构从 ROM 复制到 RAM