为了感兴趣,我想手工编译并运行最简单的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
以尽可能简化这一点,但我不明白发生了什么。我错过了什么旗帜?
答案 0 :(得分:4)
加载和执行程序还有一些问题。正如您可以从链接器输出中猜测的那样,执行不是从main
开始,而是从_start
开始,这是由与编译器捆绑在一起的CRT(C运行时)库提供的,并与代码链接在幕后。
在您的虚拟源上执行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:你现在有一个不使用任何库等的程序。