4

只是为了兴趣,我想手动编译和运行最简单的C程序;

//t.c

int main() {
       return 0;
}

所以我想做:

  • $ cpp t.c: 在这种情况下不应该做任何事情,因为不需要做任何预处理
  • $ cc1 t.c:应该编译t.c->t.s
  • $ as -o t.o t.c: 应该组装t.s->t.o
  • $ ld t.o: 应该产生可执行文件a.out(实际上没有什么可做的)

我遇到的问题是as,因为运行最终命令会产生:

ld: warning: cannot find entry symbol _start; defaulting to 00000000000400b0

这是怎么回事?我故意遗漏了libc这一点,以使其尽可能简单,但我不明白发生了什么。我错过了什么标志?

4

2 回答 2

4

加载和执行程序还有更多内容。正如您可以从链接器输出中猜到的那样,执行不是从 开始main,而是从 开始_start,它由 CRT(C 运行时)库提供,该库与编译器捆绑在一起,并在后台与您的代码链接。

这里这里是对 Linux 上程序启动时发生的情况的一些概述。

在您cc -v -Wall的虚拟源上执行以详细查看所有必需的步骤。

于 2013-05-30T13:42:26.673 回答
2

既然你说的是最简单的程序,那么这里就是一个真正的 hack。

这适用于运行 x86_64 的 Ubuntu 12.04。如果您还有其他事情,那么这可能会提示您该做什么。

mkdir hack_code
cd hack_code
cp /usr/lib/ldscripts/elf_x86_64.x ldsimple.x

现在修改ldsimple.x为说ENTRY(main)而不是ENTRY(_start)开头。

创建这个mymain.c

int main(void)
{
    __asm__ __volatile__ (
        "movq $60, %rax\n"  /* call sys_exit */
        "movq $2,  %rdi\n"  /* return code   */
        "syscall"           /* call kernel to exit program */
    );
    return 0;
}

接着:

gcc -c mymain.c
ld -o mymain -T./ldsimple.x mymain.o

瞧:你现在有一个不使用任何库等的程序。

于 2013-05-30T14:24:27.150 回答