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

Hud*_*den 10 c linux assembly gnu-assembler ld

我无法链接2个目标文件,其中一个是从汇编语言源文件生成的,另一个是从C源文件生成的.

C源代码:

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

汇编源代码:

#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
Run Code Online (Sandbox Code Playgroud)

当我使用'gcc'编译和运行时,如下所示:

gcc main2.c strlength.s -m32 -o test
./test
echo $?
Run Code Online (Sandbox Code Playgroud)

我得到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
Run Code Online (Sandbox Code Playgroud)

我遇到了分段错误.是什么造成的?我不是100%正确遵循C调用约定吗?

Emp*_*ian 11

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

不要那样做.改为:

gcc -m32 main2.o strlength.o -o test
Run Code Online (Sandbox Code Playgroud)

(您可能不应该将测试test称为exectuable ,因为它可能与/bin/test大多数UNIX系统上的标准冲突.)

说明:UNIX二进制文件通常不会开始执行main.它们在一个名为的函数中开始执行,该函数_start来自crt1.o或类似("C运行时启动").文件是libc的一部分,它安排了各种初始化,这是正确启动应用程序所必需的.

你的程序实际上不需要任何东西libc,这就是为什么你能够将它与链接ld.

但是,请考虑main退货后会发生什么.通常,代码crt1.o将执行(相当于)exit(main(argc, argv));.由于你没有链接crt1.o,没有exit人为你做最后的决定,所以代码返回到...未定义的位置并立即崩溃.