7

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

据我所知,带有文本和 RO 属性的可执行文件存储在 ROM 中。问题是 ROM 是只读存储器,如果出现代码需要写入内存的情况怎么办?

我无法在这里举出任何例子来引用(可能我对这种情况一无所知,或者我错过了基本的东西;)但是关于这个话题的任何观点都可以极大地帮助我理解!:)

Last off - 1. 有没有这样的情况?2. 在这种情况下,将代码从 ROM 复制到 RAM 是答案吗?

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

提前谢谢了!

/多发性硬化症

4

4 回答 4

9

由于硬件限制,只读存储器是只读的。该程序可能位于EEPROM、防止写入的闪存、CD-ROM 或任何硬件物理上不允许写入的地方。如果软件写入 ROM,则硬件无法更改存储的数据,因此什么也不会发生。

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

事实上,除了在最小的嵌入式系统中,从 ROM 运行是很少见的。操作系统在运行之前将可执行代码从 ROM 复制到 RAM。有时代码在 ROM 中被压缩,必须在运行前解压到 RAM 中。如果 RAM 已满,则操作系统使用分页来管理它。从 ROM 运行如此罕见的原因是因为 ROM 比 RAM 慢,并且有时代码需要在运行之前由加载程序更改。

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

于 2010-07-05T16:27:34.897 回答
3

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

于 2010-07-05T15:30:12.377 回答
3

您想要在运行时修改代码部分的正当理由很少。编译器本身不会生成需要它的代码。

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

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

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

于 2010-07-05T19:40:29.683 回答
1

哈佛架构微控制器

许多小型微控制器(Microchip PIC、Atmel AVR、Intel 8051、Cypress PSoC 等)都具有哈佛架构。它们只能执行程序存储器(闪存或 ROM)中的代码。可以将任何字节从程序存储器复制到 RAM。然而,(2)将可执行指令从 ROM 复制到 RAM 并不是解决办法——对于这些小型微控制器,程序计数器总是指向程序存储器中的某个地址。无法在 RAM 中执行代码。

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

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

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

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

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

于 2010-07-13T17:55:19.707 回答