C启动代码只在程序集混乱的情况下编写



我知道C启动代码用于初始化C运行时环境,初始化静态变量,设置堆栈指针等,最后分支到main((。

他们说这只能用汇编语言编写,因为它是特定于平台的。然而,这难道还不能用C编写并针对特定平台进行编译吗?

函数调用当然是不可能的,因为我们";更有可能";不要在那个阶段设置堆栈指针。我仍然看不出其他主要原因。提前谢谢。

只有在以下情况下,启动代码才能用C语言编写:

  1. 实现提供了所有必要的内在功能来设置无法使用标准C设置的硬件功能
  2. 提供将代码和数据片段放在特定位置并按特定顺序放置的机制(例如,gcc对ld链接器脚本的支持(

如果两个条件都满足,则可以用C语言编写启动代码。

我为Cortex-M微控制器使用我自己用C编写的启动代码(而不是芯片供应商提供的代码(,因为ARM为CMSIS头文件提供了所有所需的内联汇编功能,基于gcc的工具链为我提供了完整的内存布局控制。

用C编写早期启动代码的大部分问题实际上是缺乏结构正确的堆栈。这比不能进行函数调用更糟糕C编译器生成的所有机器代码都假设存在一个由ABI指定的寄存器指向的堆栈,该堆栈可以在任何时候用于临时存储。改变这一假设将是相当于一个完整的"秒"的工作量;后端";对于编译器来说,这比在汇编中手工编写早期启动代码要多得多。

早期的引导程序代码在开机后启动机器,还必须执行一系列通常无法从C访问的特殊操作,如配置中断和虚拟内存。它可能必须处理未在链接地址加载的代码,或未处理重新定位表,或其他类似问题;这些也打破了C编译器所做的普遍假设(例如,它可以随时注入对memcpy的调用(。

尽管如此,用户模式C库的大多数启动代码实际上都是用C编写的,这正是您思考的原因。没有人愿意为每个受支持的ISA一遍又一遍地在汇编中编写比绝对必要的更多的代码。

一个最小的C运行时环境需要一个堆栈和一个到起始地址的跳转。在大多数体系结构上设置堆栈指针需要汇编代码。一旦堆栈可用,就可以运行从C源代码生成的代码。

ARM Cortex-M设备在重置时从矢量表加载堆栈指针和起始地址,因此实际上可以直接引导到C源代码中。

在其他体系结构上,程序集所需的最小值是设置堆栈指针,然后跳转到起始地址。此后,可以用C(甚至C++(编写其他启动任务。这样的启动代码负责建立完整的C运行时,因此不能假设静态初始化或库初始化(例如,没有堆或文件系统(,这是启动代码必须完成的事情。

从这个意义上说,您可以运行从C源代码生成的代码,但在调用main()之前,环境并不是严格一致的,因此存在一些限制。

即使在使用汇编代码的情况下,它也不需要是汇编中的整个启动代码。

相关内容

  • 没有找到相关文章

最新更新