C 手动创建和运行可执行文件
出于兴趣,我想手工编译和运行最简单的C程序C 手动创建和运行可执行文件,c,assembly,compiler-construction,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 _st
//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
,以尽可能地简化它,但我不明白发生了什么。我缺少什么标志?加载和执行程序还有更多的内容。从链接器输出可以猜到,执行不是从main
开始,而是从\u start
开始,这是由CRT(C运行时)库提供的,该库与编译器捆绑在一起,并在后台与代码链接
下面是一些关于Linux上程序启动的概述
在虚拟源代码上执行
cc-v-Wall
,查看所有需要的详细步骤。既然你说的是最简单的程序,下面是一个真正的黑客程序
这是针对运行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(\u 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
瞧:你现在有了一个不使用任何库等的程序。哦,我需要链接到
crt1.o
?是的,crt1.o将提供_start,你真的应该在预处理后有一个中间文件,因为它是预处理程序,将删除顶部的注释(虽然传递它可能不会影响下一次传递)。@LeeDanielCrocker的确,编译器接受仍然包含注释的“预处理”文件。如果出于某种原因需要,GCC的预处理器甚至可以将它们保留在其中。非常好的链接。非常感谢。这正是我想要的。