Assembly 微控制器的C启动代码是什么?何时/为什么/如何修改?

Assembly 微控制器的C启动代码是什么?何时/为什么/如何修改?,assembly,microcontroller,startup,Assembly,Microcontroller,Startup,这是关于启动代码的一般问题。我知道这就像引导加载程序,或者在重置或通电后运行的第一件事,它调用主函数 但我想知道它的主要/核心功能 例如(在谷歌搜索) 目标系统复位后,立即执行启动代码。凯尔创业公司 代码按顺序执行(可选)以下操作:  Clears internal data memory  Clears external data memory  Clears paged external data memory  Initializes the small model reentra

这是关于启动代码的一般问题。我知道这就像引导加载程序,或者在重置或通电后运行的第一件事,它调用主函数

但我想知道它的主要/核心功能

例如(在谷歌搜索)

目标系统复位后,立即执行启动代码。凯尔创业公司 代码按顺序执行(可选)以下操作:

 Clears internal data memory
 Clears external data memory
 Clears paged external data memory
 Initializes the small model reentrant stack and pointer
 Initializes the large model reentrant stack and pointer
 Initializes the compact model reentrant stack and pointer
 Initializes the 8051 hardware stack pointer
 Transfers control to code that initializes global variables or to the main C function if
there are no initialized global variables
注意:启动代码总是在汇编中编写的,因为它取决于CPU目标


感谢您抽出时间

所有计算机程序都是在这样的假设下工作的,即它们所执行的世界是按照它们的期望设置的

假设您有一个程序p,它假设变量X的值在p启动时为零

如果你把程序p作为代码启动点放在你的微处理器里,它就不能工作了。。。。因为X的值不能保证为零。(RAM内存位置倾向于接通包含垃圾的电源。)

您可以通过插入使假设为真的启动代码来解决该问题,例如,在启动时将代码放置为变量X的零,然后将控制传递给您的程序。无论程序需要什么样的假设,都需要在启动代码中实现

现在我写了一个相当笼统的描述。当我们谈论真正的微处理器时,通常必须满足一些低级假设:

  • 如果机器有一个堆栈指针,它会指向一些实际内存,而不是存放垃圾
  • 任何I/O端口或特殊硬件都需要“准备使用”(它们经常需要配置;考虑内存库登记寄存器或优先级中断控制器)
  • 程序的位置是已知的
如果需要这三个假设,启动代码将通过以下方式解决:

  • 使用已知为RAM地址的常量加载SP寄存器
  • 执行特殊指令或将各种魔术常量写入必要的I/O端口以配置它们以供使用
  • 将电脑设置到程序的已知位置(通常是JMP xxxx指令)
每个MCU控制器程序对世界都有不同的假设。您可以自定义启动代码以满足这些假设


一般来说,这些假设并不多,许多MCU程序都可以通过一个小的、精心选择的集合来完成。因此,启动指令往往与程序分开处理(否则,您可以简单地将它们预先添加到程序中,有时人们会这样做)

您提到启动代码调用main,所以我假设您所说的是C/C++应用程序的启动代码。启动代码负责为应用程序设置C运行时环境。这包括:

  • 将初始化变量的初始值从ROM复制到RAM
  • 为未初始化的变量调零RAM
  • 设置堆栈指针
  • 对于C++应用程序,它调用任何全局或静态对象实例的构造函数< /LI>
  • 最后,呼叫main
启动代码也可以进行一些硬件初始化,但这是特定于硬件的,不一定是要求。例如,如果硬件使用PLL提高时钟频率,那么启动代码可能会首先设置PLL,以便剩余的启动代码以全速执行。如果电路板在地址/数据总线上有外部设备,则处理器的外部内存控制器通常在启动代码中配置。或者,如果硬件有一个看门狗,那么启动代码可能会禁用它,以便在应用程序有机会配置它之前不会重置它

我通常不会在启动代码中进行特定于应用程序的硬件初始化。相反,在调用main之后,我将初始化应用程序中的GPIO、计时器和串行端口


编译器工具链通常为其支持的硬件环境提供启动代码。此示例启动代码可能适用于大多数应用程序,您可能永远不需要修改它。但是,如果您的硬件或运行时环境有专门的功能,那么您可能需要自定义启动代码。当我不得不自定义启动代码时,我总是以示例启动代码为例,对其进行修改以满足我的需要。我不记得曾经从头开始写过启动代码。

启动代码就是这样。这是启动时运行的代码。它会做任何它需要做的事情来准备其余的代码执行。没有比这更好的答案了。你可能会问,计算机程序一般都做些什么。@RossRidge我不明白你的意思。启动代码非常具体,我不认为这是一个一般性的问题。正如我所说,你可以谈论任何类型的MCU。RegardsStartup代码还负责将硬件初始化到定义的状态,这对于车载计算机和核电厂来说显然是完全不同的。它不必是组装的,但如果不是,你就有鸡和蛋的问题,C代码为C做引导(如果使用C)无法做出与普通C程序相同的假设(存在已初始化的.data,.bss为零,无法使用具有这些假设的任何其他C代码(memset,memcpy))。因此,通常使用asm来避免该问题。但这并不是严格要求的。