如何链接C对象文件和汇编语言对象文件?

问题描述:

我无法链接2个对象文件,其中一个是从汇编语言源文件生成的,另一个是从C源文件生成的。如何链接C对象文件和汇编语言对象文件?

C源代码:

//main2.c 
extern int strlength(char *); 
int main(){ 
    char * test = "hello"; 
    int num = strlength(test); 
    return num; 
} 

汇编源代码:

#strlength.s 
.include "Linux32.s" 

.section .text 
.globl strlength 
.type strlength, @function 
strlength: 
pushl %ebp 
movl %esp, %ebp 
movl $0, %ecx 
movl 8(%ebp), %edx 
read_next_byte: 
movb (%edx), %al 
cmpb $END_OF_FILE, %al 
jle end 
incl %edx 
incl %ecx 
jmp read_next_byte 
end: 
movl %ecx, %eax 
popl %ebp 
ret 

当我编译和运行程序使用 'GCC' 是这样的:

gcc main2.c strlength.s -m32 -o test 
./test 
echo $? 

我得到5,它是正确。然而,当我编译/汇编分开,然后用“LD” 这样的链接:

as strlength.s --32 -o strlength.o 
cc main2.c -m32 -o main2.o 
ld -melf_i386 -e main main2.o strlength.o -o test 
./test 

我得到一个分段错误。这是什么造成的?我没有正确遵循C调用约定吗?

ld -melf_i386 -e main main2.o strlength.o -o test

不要那样做。做到这一点,而不是:

gcc -m32 main2.o strlength.o -o test 

(你可能不应该打电话给你测试exectuable test,因为它可能与/bin/test冲突,在大多数UNIX系统的标准。)

说明:UNIX二进制文件做一般开始执行main。他们开始执行一个名为_start的函数,该函数来自crt1.o或类似的函数(“C运行时启动”)。 文件是libc的一部分,它安排了各种初始化,这是适当启动应用程序所必需的。

你的程序实际上不需要任何libc,这就是为什么你可以把它与ld链接。

但是,请考虑您的main返回后会发生什么情况。 通常crt1.o中的代码将执行(相当于)exit(main(argc, argv));。既然你链接没有crt1.o,没有人为你做最后的exit,所以代码返回...未定义的位置,并迅速崩溃。

您还需要链接crt1.o(可能有不同的名称,包含必要的代码,直到main可以调用)和必要的库。 GCC通常还需要链接到libgcc.so,其中包含必要的帮助函数(例如,在32位系统上执行64位计算时)以及其他系统库。例如,在我的Mac上,它也需要链接到libSystem,其中还包含通常的C函数,如printf。在Linux上,通常是libc

请注意,你的程序不能直接与main开始(因为你正在试图做的与ld .. -e main),入口点需要几件事情成立调用C函数main之前。这就是前面提到的crt1.o正在做的事情。我猜想分段错误是由于这种缺失设置造成的。

要了解GCC正好做系统,请致电:

gcc main2.c strlength.s -m32 -o test -v