为什么需要链接描述文件和启动代码?
why need linker script and startup code?
我可以按照指南和 运行 代码进行操作。但我有疑问。
1) 为什么我们需要加载地址和运行-时间地址。据我了解,这是因为我们也将 .data 放在了闪存中;那么为什么我们不 运行 应用程序在那里,而是需要启动代码将其复制到 RAM 中?
http://www.bravegnu.org/gnu-eprog/c-startup.html
2) 为什么我们需要链接描述文件和启动代码。我不能像下面那样构建 C 源代码然后 运行 使用 qemu 吗?
arm-none-eabi-gcc -nostdlib -o sum_array.elf sum_array.c
非常感谢
1) .data 部分包含变量。好吧,变量是可变的——它们在 运行 时间发生变化。变量需要在 RAM 中,以便可以在 运行 时轻松更改它们。与 RAM 不同,Flash 在 运行 时间不容易更改。闪存包含 .data 部分中变量的初始值。启动代码将 .data 部分从闪存复制到 RAM 以初始化 RAM 中的 运行 时间变量。
2) 链接器脚本:您的编译器创建的目标代码尚未定位到微控制器的内存映射中。这是链接器的工作,这就是您需要链接描述文件的原因。链接器脚本是链接器的输入,提供了一些关于系统内存的位置和范围的指令。
启动代码:从 main
开始的 C 程序并不是凭空 运行 而是对环境做出一些假设。例如,它假定初始化变量在 main
执行之前已经初始化。当 main
执行时(即 "run-time environment"),启动代码是必要的,以放置所有假设到位的东西。堆栈指针是在 main
执行之前在启动代码中初始化的另一个例子。如果您使用 C++,则在 main
执行之前从启动代码调用静态对象的构造函数。
1) Why do we need both load-address and run-time address.
虽然在大多数情况下可以 运行 从内存映射 ROM 编写代码,但通常代码从 RAM 执行起来会更快。在某些情况下,可能还有更大的 RAM,ROM 和应用程序代码可能会压缩到 ROM 中,因此可执行代码可能不会简单地从 ROM 复制并解压缩 - 允许比可用 ROM 大得多的应用程序。
在代码存储在非内存映射大容量存储介质(如 NAND 闪存)的情况下,无论如何都不能直接执行,必须通过某种引导加载程序加载到 RAM 中。
2) Why we need linker script and start-up code here. Can I not just build C source as below and run it with qemu?
链接描述文件定义了目标和应用程序的内存布局。由于本教程是针对裸机编程的,因此没有 OS 可以为您处理。类似地,启动代码至少需要设置一个初始堆栈指针、初始化静态数据并跳转到 main。在嵌入式系统上,还需要初始化各种硬件,例如 PLL、内存控制器等
您的第一个问题已在指南中得到解答。
当您在操作系统上加载程序时,您的 .data 部分(基本上是非零全局变量)会从 "binary" 加载到内存中的正确偏移量中,因此当您的程序启动这些代表变量的内存位置具有这些值。
unsigned int x=5;
unsigned int y;
作为一名 C 程序员,您在编写上述代码时希望 x 为 5,是吗?好吧,如果从闪存、裸机启动,您没有操作系统可以为您将该值复制到 ram,必须有人来做。此外,所有 .data 内容都必须在闪存中,数字 5 必须在闪存中的某个位置,以便可以将其复制到 ram。所以你需要一个闪存地址和一个内存地址。同一事物的两个地址。
这就开始回答您的第二个问题,对于您编写的每一行 C 代码,您都假设诸如任何函数都可以调用任何其他函数之类的事情。您希望能够调用函数是吗?并且您希望能够拥有局部变量,并且您希望上面的变量 x 为 5,并且您可能假设 y 将为零,尽管谢天谢地,编译器开始对此发出警告。通用 C 的启动代码至少设置了堆栈指针,它允许您调用其他函数并具有局部变量并且具有超过一两行代码长的函数,它将 .bss 归零,以便上面的 y 变量为零,它将值 5 复制到 ram,以便当您的入口点 C 函数的代码为 运行 时,x 已准备就绪。
如果您没有操作系统,那么您必须有代码来执行此操作,是的,有许多沙箱和工具链是为各种平台设置的,这些平台已经具有启动和链接器脚本,因此您可以
gcc -O myprog.elf myprog.c
现在这并不意味着您可以在没有...system...printf、fopen 等的情况下进行系统调用。但是如果您下载这些工具链之一,则意味着您实际上不必编写链接描述文件也不是 bootstrap.
但这仍然是有价值的信息,请注意,基于操作系统的程序也需要启动代码和链接描述文件,只是您的操作系统的本机编译器假设您将主要为该操作系统编写程序系统,因此他们在该工具链中提供了链接描述文件和启动代码。
我可以按照指南和 运行 代码进行操作。但我有疑问。
1) 为什么我们需要加载地址和运行-时间地址。据我了解,这是因为我们也将 .data 放在了闪存中;那么为什么我们不 运行 应用程序在那里,而是需要启动代码将其复制到 RAM 中?
http://www.bravegnu.org/gnu-eprog/c-startup.html
2) 为什么我们需要链接描述文件和启动代码。我不能像下面那样构建 C 源代码然后 运行 使用 qemu 吗?
arm-none-eabi-gcc -nostdlib -o sum_array.elf sum_array.c
非常感谢
1) .data 部分包含变量。好吧,变量是可变的——它们在 运行 时间发生变化。变量需要在 RAM 中,以便可以在 运行 时轻松更改它们。与 RAM 不同,Flash 在 运行 时间不容易更改。闪存包含 .data 部分中变量的初始值。启动代码将 .data 部分从闪存复制到 RAM 以初始化 RAM 中的 运行 时间变量。
2) 链接器脚本:您的编译器创建的目标代码尚未定位到微控制器的内存映射中。这是链接器的工作,这就是您需要链接描述文件的原因。链接器脚本是链接器的输入,提供了一些关于系统内存的位置和范围的指令。
启动代码:从 main
开始的 C 程序并不是凭空 运行 而是对环境做出一些假设。例如,它假定初始化变量在 main
执行之前已经初始化。当 main
执行时(即 "run-time environment"),启动代码是必要的,以放置所有假设到位的东西。堆栈指针是在 main
执行之前在启动代码中初始化的另一个例子。如果您使用 C++,则在 main
执行之前从启动代码调用静态对象的构造函数。
1) Why do we need both load-address and run-time address.
虽然在大多数情况下可以 运行 从内存映射 ROM 编写代码,但通常代码从 RAM 执行起来会更快。在某些情况下,可能还有更大的 RAM,ROM 和应用程序代码可能会压缩到 ROM 中,因此可执行代码可能不会简单地从 ROM 复制并解压缩 - 允许比可用 ROM 大得多的应用程序。
在代码存储在非内存映射大容量存储介质(如 NAND 闪存)的情况下,无论如何都不能直接执行,必须通过某种引导加载程序加载到 RAM 中。
2) Why we need linker script and start-up code here. Can I not just build C source as below and run it with qemu?
链接描述文件定义了目标和应用程序的内存布局。由于本教程是针对裸机编程的,因此没有 OS 可以为您处理。类似地,启动代码至少需要设置一个初始堆栈指针、初始化静态数据并跳转到 main。在嵌入式系统上,还需要初始化各种硬件,例如 PLL、内存控制器等
您的第一个问题已在指南中得到解答。
当您在操作系统上加载程序时,您的 .data 部分(基本上是非零全局变量)会从 "binary" 加载到内存中的正确偏移量中,因此当您的程序启动这些代表变量的内存位置具有这些值。
unsigned int x=5;
unsigned int y;
作为一名 C 程序员,您在编写上述代码时希望 x 为 5,是吗?好吧,如果从闪存、裸机启动,您没有操作系统可以为您将该值复制到 ram,必须有人来做。此外,所有 .data 内容都必须在闪存中,数字 5 必须在闪存中的某个位置,以便可以将其复制到 ram。所以你需要一个闪存地址和一个内存地址。同一事物的两个地址。
这就开始回答您的第二个问题,对于您编写的每一行 C 代码,您都假设诸如任何函数都可以调用任何其他函数之类的事情。您希望能够调用函数是吗?并且您希望能够拥有局部变量,并且您希望上面的变量 x 为 5,并且您可能假设 y 将为零,尽管谢天谢地,编译器开始对此发出警告。通用 C 的启动代码至少设置了堆栈指针,它允许您调用其他函数并具有局部变量并且具有超过一两行代码长的函数,它将 .bss 归零,以便上面的 y 变量为零,它将值 5 复制到 ram,以便当您的入口点 C 函数的代码为 运行 时,x 已准备就绪。
如果您没有操作系统,那么您必须有代码来执行此操作,是的,有许多沙箱和工具链是为各种平台设置的,这些平台已经具有启动和链接器脚本,因此您可以
gcc -O myprog.elf myprog.c
现在这并不意味着您可以在没有...system...printf、fopen 等的情况下进行系统调用。但是如果您下载这些工具链之一,则意味着您实际上不必编写链接描述文件也不是 bootstrap.
但这仍然是有价值的信息,请注意,基于操作系统的程序也需要启动代码和链接描述文件,只是您的操作系统的本机编译器假设您将主要为该操作系统编写程序系统,因此他们在该工具链中提供了链接描述文件和启动代码。