手动创建和运行可执行文件

时间:2013-05-30 13:22:56

标签: c assembly compiler-construction

为了感兴趣,我想手工编译并运行最简单的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以尽可能简化这一点,但我不明白发生了什么。我错过了什么旗帜?

2 个答案:

答案 0 :(得分:4)

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

Herehere概述了Linux上程序启动时发生的事情。

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

答案 1 :(得分:2)

既然你说了最简单的程序,那么这是一个真正的黑客。

这适用于运行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

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