静态编译libc C代码和ASM代码

我有ASM代码:

extern my_func extern printf extern exit global _start section .data ... section .text _start: ... call printf ... call my_func ... call exit 

和C代码:

  int my_func(int a, int b) { return a+b; } 

我在64位机器上使用fedora。 我希望可执行文件是32位。 对于动态链接我做:

 nasm -f elf32 asm.asm ; this gives me asm.o gcc -m32 -Wall -c c_code.c ; this gives me c_code.o ld c_code.o asm.o -melf_i386 -L /usr/lib/ -lc -I /lib/ld-linux.so.2 ; this gives me a.out which runs fine and weights 5601 bytes. 

我想要做的是静态链接libc。 我做了以下事情:

 gcc -o a2.out -m32 -static -m32 asm.o c_code.o 

我得到错误:

 asm.o: In function `_start': asm.asm:(.text+0x0): multiple definition of `_start' /usr/lib/gcc/x86_64-redhat-linux/4.8.3/../../../../lib64/crt1.o:(.text+0x0): first defined here collect2: error: ld returned 1 exit status 

然后我在ASM代码中将_start更改为main,整个链接很好! ldd显示“不是动态可执行文件”。 但是文件创建的权重为721067字节! 我认为它静态编译了许多不必要的代码。 所以,我的第一个问题是:

1)如何仅为所需的printf和退出函数静态链接libc?

当我尝试

 gcc -m32 -o a3.out -lc asm.o c_code.o ; ASM file has main instead of _start 

我得到一个权重7406字节的文件。 ldd显示与a.out相同的动态库,其权重为5601字节。

2)为什么会有这种差异? 看起来像我的代码中“连接”_start与main的一些额外代码… 3)链接gcc和ld有什么区别?

非常感谢您的关注!

1)如何仅为所需的printf和退出函数静态链接libc?

尝试使用-nostartfiles -static -nostdlib -lc进行编译,这将避免添加crt1.o和crtend.o。 但请记住,这将禁用所有Glibc初始化代码,因此某些Glibc函数将无法工作。

2)为什么会有这种差异? 看起来像我的代码中“连接”_start与main的一些额外代码……

GCC添加执行初始化的启动文件( crt*.o )。 有关详细信息,请参阅许多在线文章(例如本文 )。

3)链接gcc和ld有什么区别?

已经在上面回答了,但一般来说你可以运行gcc -v并检查ld(或collect2)的参数。