基于ROM的可执行文件的基本问题

时间:2010-07-05 15:22:13

标签: operating-system cpu computer-architecture embedded

我对存储在ROM中的可执行文件存在基本疑问。

据我所知,带有文本和RO属性的可执行文件存储在ROM中。问题是ROM是否为只读存储器,如果存在代码需要写入存储器的情况会发生什么?

我无法想出任何一个例子来引用这里(可能我对这种情况一无所知或者我错过了基本的东西;)但是这个主题的任何亮点都可以帮助我理解! :)

最后关闭 - 1.有这种情况吗? 2.在这种情况下,将代码从ROM复制到RAM是答案吗?

回答一些例子可以大大帮助..

非常感谢提前!

/ MS

4 个答案:

答案 0 :(得分:8)

只读内存因硬件限制而被读取。该程序可能位于EEPROM,闪存保护,不受写入,CD-ROM或硬件物理上不允许写入的任何内容。如果软件写入ROM,则硬件无法更改存储的数据,因此没有任何反应。

因此,如果ROM中的软件程序想要写入内存,则会写入RAM。这是唯一的选择。如果一个程序从ROM运行并想要change itself,它就不能,因为它无法写入ROM。但是,是的,该程序可以从RAM运行。

事实上,除了最小的嵌入式系统外,从ROM运行很少见。操作系统在运行之前将可执行代码从ROM复制到RAM。 ROM中有时code is compressed,必须在运行前解压缩到RAM中。如果RAM已满,操作系统将使用paging进行管理。从ROM运行的原因是如此罕见,因为ROM比RAM慢,有时代码需要在运行前由loader更改。

请注意,如果您有自己修改的代码,则必须了解您的系统。许多系统使用data-execution prevention(DEP)。可执行代码进入RAM的读取+执行区域。数据进入读/写区域。所以在这些系统上,代码永远不会在RAM中自行改变。

答案 1 :(得分:3)

通常只有程序代码,常量和初始化数据存储在ROM中。 RAM中的单独存储区用于堆栈,堆等。

答案 2 :(得分:3)

您可能希望在运行时修改代码部分的合理原因很少。编译器本身不会生成需要的代码。

您的链接器可以选择生成MAP文件。这将告诉您所有内存对象的位置。

链接器根据链接描述(您可以根据需要自定义组织内存)选择查找位置。通常在基于FLASH的微控制器代码和常量数据将被放置在ROM中。同样放在ROM中的是非零初始化静态数据的初始化数据,在调用main()之前将其复制到RAM。零初始化静态数据在main()之前简单地清零。

可以安排链接器在ROM中找到部分或全部代码,并使运行时启动代码以与非零静态数据相同的方式将其复制到RAM,但代码必须是可重定位的或者在第一个实例中位于RAM中,你通常不能只将从ROM运行的代码复制到RAM并期望它运行,因为它可能有绝对地址引用(除非你的目标有一个MMU和可以重新映射地址空间)。通常在微控制器上的RAM中定位以提高执行速度,因为当使用高时钟速度时RAM通常比FLASH更快,产生更少或零等待状态。当代码在运行时从文件系统加载而不是存储在ROM中时,也可以使用它。即使加载到RAM中,如果处理器有MMU,RAM部分中的代码部分也可能被标记为只读。

答案 3 :(得分:1)

哈佛架构微控制器

许多小型微控制器(Microchip PIC,Atmel AVR,Intel 8051,Cypress PSoC等)采用哈佛架构。 它们只能从程序存储器(闪存或ROM)执行代码。 可以将任何字节从程序存储器复制到RAM。 但是,(2)将可执行指令从ROM复制到RAM不是答案 - 对于这些小型微控制器,程序计数器总是指程序存储器中的某个地址。在RAM中执行代码是不可能的。

数据从ROM复制到RAM非常常见。 首次上电时,典型的固件应用程序将所有RAM归零,然后在main()启动之前将非const全局变量和静态变量的初始值从ROM复制到RAM中。 每当应用程序需要将一个固定的字符串从串口中推出时,它就会从ROM中读取该字符串。

对于这些微控制器的早期版本,连接到微控制器的外部“器件编程器”是改变程序的唯一方法。 在正常操作中,该设备远不是“设备编程器”。 如果在微控制器上运行的软件需要写入程序存储器ROM - 对不起,太糟糕了 - 这是不可能的。 许多嵌入式系统具有代码可以写入的非易失性EEPROM - 但这仅用于存储数据值。微控制器只能执行程序ROM中的代码,而不能执行EEPROM或RAM。 人们用这些微控制器做了很多事情,包括BASIC解释器和字节码Forth解释器。 显然(1)代码永远不需要写入程序存储器。

最近有一些“自编程”微控制器(来自Atmel,Microchip,Cypress等), 芯片上有特殊的硬件,允许在微控制器上运行的软件擦除和重新编程自己程序存储器闪存的块。 一些应用程序使用这种“自编程”功能来读取和写入“额外”闪存块的数据 - 从未执行的数据,因此它不算作自修改代码 - 但这不做任何事情你不能用更大的EEPROM。 到目前为止,我只看到在哈佛架构微控制器上运行的两种软件,它们将新的可执行软件写入自己的程序Flash:bootloaders和Forth编译器。

当Arduino引导加载程序(引导加载程序)运行并检测到新的应用程序固件映像可用时,它会下载新的应用程序固件(进入RAM),并将其写入Flash。 下次打开系统时,它现在运行闪亮的新版本16.98应用程序固件,而不是笨重的旧版本16.97应用程序固件。 (当然,包含引导加载程序本身的Flash块保持不变)。 如果没有写入程序存储器的“自编程”功能,这是不可能的。

一些Forth实现在一个小型微控制器上运行,编译新的可执行代码并使用“自编程”功能将其存储在程序Flash中 - 这个过程有点类似于JVM的“即时”编译。 (所有其他语言似乎都需要编译器太大而且复杂,无法在小型微控制器上运行,因此编辑 - 编译 - 下载 - 运行周期需要更长的挂钟时间。)