您所说的是嵌入式世界中所谓的“裸机”应用程序。它们对于诸如 ARM Cortex-M3 之类的东西非常常见,它放入(比如)借记卡验证器盒或交互式玩具中,并且没有足够的内存或能力来运行完整的操作系统。因此,您无需使用“ARM/Linux”编译器来编译应用程序以在 ARM 处理器上运行在 Linux 上,而是获得“ARM 裸机”编译器,该编译器可以在没有操作系统的情况下编译运行在 ARM 处理器上的东西。(我使用 ARM 而不是 x86 作为示例,因为 x86 裸机应用程序现在非常罕见。)
正如您的问题和其他答案中所述,您的应用程序将需要执行一些原本由操作系统处理的事情。
首先,它需要初始化内存系统、中断向量和其他各种 board goo 位。通常这是裸机编译器会为您做的事情,但如果您有一块奇怪的板,您可能需要告诉它如何做到这一点。这会从板子打开的位置到您的 main() 函数开始的位置。
然后,您需要与 CPU 和 RAM 之外的事物进行交互。操作系统包括执行此操作的各种功能——磁盘 I/O、屏幕输出、键盘和鼠标输入、网络等,等等。如果没有操作系统,您必须从其他地方获取它。您可以从硬件制造商的库中获得其中的一些;例如,我最近玩的一块板子有一个 40x200 像素的 LED 屏幕,它带有一个库,其中包含打开它并在其上设置单个像素值的代码。并且有几家公司出售库来实现 TCP/IP 堆栈之类的东西,用于网络或诸如此类的东西。
例如,考虑一下这使得即使是基本的 printf 也变得困难。当你有一个操作系统时, printf 只是向操作系统发送一条消息,说“把这个字符串放在控制台上”,操作系统会在控制台上找到当前光标位置,并做所有的事情来找出什么像素在屏幕上进行更改,以及使用什么 CPU 指令来更改这些像素,以便做到这一点。
哦,我们有没有提到您首先必须弄清楚如何将程序放入 CPU 中?典型的计算机具有一些可编程 ROM,它将在启动时加载指令。在 x86 上,这是 BIOS,它通常已经包含一个方便的程序,可以启动 CPU、设置显示、查找磁盘以及从找到的磁盘加载程序。在嵌入式系统上,这通常是您的程序所在的位置——这意味着您需要某种方式将您的程序放在那里。通常,这意味着您有一个称为“调试器”的设备,它物理地连接到您的嵌入式板以加载程序 - 并且还可以执行允许您暂停处理器并确定其状态的事情,这样您就可以单步执行您的程序,就像您在计算机上的软件调试器中运行它一样。但我离题了。
无论如何,要回答你的第二个问题,你要创建的这个可执行文件是存储在嵌入式板上的那个 ROM 中的东西——或者你可能只是将它的一部分存储在 ROM 中(毕竟,这很漂亮小)并将其余部分存储在闪存驱动器上,ROM中的位将包含将其余部分从闪存驱动器中取出的指令。它可能会作为文件存储在您的主计算机(即您正在创建它的 Linux 或 Windows 计算机)上,但这只是为了存储,它不会在那里运行。
您会注意到,当您将大量此类库放在一起时,它们的功能与操作系统的功能相当,并且在一堆库和真正的操作系统之间存在一定的空间。在那个空间里有所谓的 RTOS——“实时操作系统”。其中较小的实际上只是库的集合,它们一起工作以完成所有操作系统的事情,有时还包括一些东西,这样你就可以一次运行多个线程(然后你可以让不同的线程像不同的程序一样工作) - - 尽管所有这些都被编译到同一个编译的“程序”中,而 RTOS 实际上只不过是您包含的一个库。较大的开始将部分代码存储在不同的地方,而且我认为其中一些甚至可以从磁盘加载代码片段——就像 Windows 和 Linux 在运行程序时所做的那样。这是一个连续统一体,而不是非此即彼的。
FreeRTOS 系统是一个开源的 RTOS,它接近 RTOS 空间的较小端;如果您更感兴趣,它们可能是查看其中一些内容的好地方。他们确实有一些 x86 应用程序的示例,可以让您了解什么样的 x86 系统可以运行裸机或基于 RTOS 的程序,以及如何编译一些东西以在其中运行;链接在这里:http ://www.freertos.org/a00090.html#186 。