【问题标题】:Creating and running executable by hand手动创建和运行可执行文件
【发布时间】:2013-05-26 02:25:48
【问题描述】:

为了兴趣,我想手工编译运行最简单的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 以保持尽可能简单,但我不明白发生了什么。我错过了哪些标志?

【问题讨论】:

  • 哦,我需要链接crt1.o吗?
  • 是的,crt1.o 将提供_start
  • 而且你真的应该在预处理之后有一个中间文件,因为它是预处理器会在顶部删除你的评论(尽管传递它可能不会损害下一次传递)。
  • @LeeDanielCrocker 实际上,编译器接受仍然包含 cmets 的“预处理”文件。如果出于某种原因需要,GCC 的预处理器甚至可以选择保留它们。

标签: c assembly compiler-construction


【解决方案1】:

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

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

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

【讨论】:

  • 很棒,很棒的链接。非常感谢。正是我想要的。
【解决方案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

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

【讨论】:

    猜你喜欢
    • 2011-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-27
    • 2020-08-07
    • 2011-09-27
    相关资源
    最近更新 更多