c - 用 C 和基本库烘焙 PI

标签 c assembly arm mingw yagarto

我有以下问题 - 我已经完成了烘焙 pi 类(class),没有任何问题,然后我决定将这个纯 asm 与一些 C 链接。我已经做到了,就我决定使用而言,一切都很好函数 sprintf 将 int 转换为 char*。现在,当我尝试编译时,我正在享受以下错误

ctesty.c:(.text+0x20): 未定义对“sprintf”的引用 make: *** [build/output.elf] 错误 1

当然,我已经包含了 stdio.h,我也试图将这个库直接包含在 makefile 中,但没有成功。

最佳答案

您想与 libc.so 链接。尝试在您的 makefile 的链接步骤中添加 -lc

在更好地理解问题后更新

Baking Pi示例构建一个 kernel.img 来代替通常的 Linux 内核运行。这意味着 C 标准库不可用。您需要提供自己的 sprintf() 实现,例如:

  • 改编此 BSD 许可 ee_printf.c
  • 移除uart_send_char()
  • 通过使 buf 成为函数参数,将 ee_printf() 适配到 sprintf()

为什么用户空间 libc 在任何内核中都没有源代码修改就无法工作

概念上:

  • C 标准库包含处理动态内存分配(mallocfree)、文件系统(fopen)的工具fclose 和所有 stdio)、环境变量(getenv)、错误处理工具,如 setjmp longjmp 等等。
  • 考虑:您将如何在操作系统下运行的程序中实现malloc
    • 回答:您需要一些接口(interface)来向操作系统请求额外的内存,例如Linux 下的brksbrkmmap
    • 在操作系统内核中,brkmmap 等不是分配内存的正确接口(interface)。
    • 因此,尽管大多数非玩具内核提供类似 malloc 的设施,但它们将无法使用未修改的用户空间 malloc 实现。
  • 在操作系统内核中,fopengetenv 等函数并不是那么有用。大多数内核编写者选择不包含它们。
  • 因此大多数内核不包含完整的 C 标准库实现,而只包含内核编写者认为有用的函数。

在更机械的意义上:

  • Baking Pi Makefile使用命令生成内核 ELF 镜像 $(ARMGNU)-ld --no-undefined $(OBJECTS) -Map $(MAP) -o $(BUILD)output.elf -T $(LINKER)。这不会将 build/output.elf 与任何 libc 实现链接起来,因此链接器将无法找到名为 sprintf 的符号。
  • 当您使用 gcc T.c -o T 构建程序时,gcc 会隐式链接到 libc 中,除非传递了诸如 -nostdlib 之类的选项。

但概念上重要的几点是:

  • 在内核中有用的 C 标准库部分需要不同的实现
  • libc 的许多其他部分在内核中用处不大

有针对裸机环境的 C 标准库实现。参见例如 newlib .

关于c - 用 C 和基本库烘焙 PI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24367079/

相关文章:

c - 关于内存对齐的一些困惑

c - 为 ATMEGA128 uc 实现接收中断超时

assembly - 内存地址和偏移量

assembly - MIPS 计数 MARS 中 1's given a user input (B instruction doesn' t 跳转的数量)

c - 当我们用完 Cortex M3 上的内存时会发生什么

c - 输出到汇编中的设备

c - 经历 APR 失败

c - 为什么这个程序不能无限运行?

c - 程序集如何访问/存储堆栈上的变量

c++ - 使用arm-linux-gnueabi-g++ -o时出现段错误,没有-o则没有问题