在Linux下编译C++代码时如何不使用运行库

8
最近我开始探索生成的代码如何使用C++运行库。 主要是出于好奇,但我也希望评估开发启动C++内核所需的最小必要工作量。 因此,我开始实现自己的运行库,但遇到了一些小问题。
int main(int argc, char **argv)
{
  return 0;
}

使用以下命令编译:

$ g++ -ffreestanding -nostdlib -fno-builtin -fno-rtti -fno-exceptions -c main.cpp

会出现以下警告:

/usr/bin/ld: 警告: 找不到入口符号 _start;默认为 00000000080480b8

然后当我尝试执行生成的二进制文件时,会出现“Segmentation fault”错误。我已经尝试编译“main.cpp”和一个ASM文件。
[global _start]
[extern main]

_start:
  call main

手动使用“ld”链接目标文件时,我没有警告,但二进制文件仍会引发“分段错误”。
我想我正在失落某些东西。可能是在调用“main”之前和之后必须完成的某些事情,就像系统C库中的“__libc_start_main”一样。
此外,如果有人对我应该阅读的有关此主题的网站、文档或书籍有任何建议,我将非常感激。
谢谢,
帕特里克

5
如何构建最小的Unix可执行文件。 - QuantumMechanic
3个回答

5

好的,感谢QuantumMechanic提供的链接,我找到了问题所在: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

我只是忘记了我的Linux编程基础,更重要的是如何处理程序结束。

基本上,我需要生成系统调用中断“exit”来处理程序的结束。

[BITS 32]

[global _start]
[extern main]

_start:
  call main
  mov ebx, eax  ; Move the returned value in the register used as argument of exit()
  mov eax, 1    ; Indicates the id of the syscall to execute
  int 0x80      ; Triggers the syscall interrupt

现在,我可以使用自己的RTL在Linux上编译任何C ++程序以进行测试。

请注意,如果 "main" 函数的末尾永远不会到达,则内核中将不需要它。

谢谢!


1

如果您愿意使用gcc安装的(200K)部分,您可以链接libgcc_s。这将为您提供所需的所有代码,以使您的程序进行静态初始化并调用main


1

当你构建内核时,你必须考虑它如何启动。通常这是引导加载程序的责任,而它们远非标准化。这显然不像启动Linux应用程序那样简单。因此,如果你打算忽略这种启动方式,那么担心 _start 实际上并不太明智。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接