Linux 如何将 C 目标文件与汇编语言目标文件链接起来?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8691138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:52:42  来源:igfitidea点击:

How to link a C object file with a Assembly Language object file?

clinuxassemblyldgas

提问by Hudson Worden

I am having trouble linking 2 object files one of which was generated from an Assembly Language Source File and another that was generated from a C Source file.

我在链接 2 个目标文件时遇到问题,其中一个是从汇编语言源文件生成的,另一个是从 C 源文件生成的。

C source code:

C源代码:

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

Assembly source code:

汇编源代码:

#strlength.s
.include "Linux32.s"

.section .text
.globl strlength
.type strlength, @function
strlength:
 pushl %ebp
 movl %esp, %ebp
 movl 
gcc main2.c strlength.s -m32 -o test
./test
echo $?
, %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

When I compile and run using 'gcc' like this:

当我像这样使用“gcc”编译和运行时:

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

I get 5 which is correct. However when I compile/assemble separately and then link with 'ld' like this:

我得到 5,这是正确的。但是,当我单独编译/组装然后像这样与“ld”链接时:

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

I get a segmentation fault. What is causing this? Am I not following the C calling convention 100% correctly?

我收到分段错误。这是什么原因造成的?我是否没有 100% 正确地遵循 C 调用约定?

采纳答案by Employed Russian

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

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

Don't do that. Do this instead:

不要那样做。改为这样做:

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

(You should probably not call your test exectuable test, as it may conflict with the /bin/test, standard on most UNIX systems.)

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

Explanation: UNIX binaries do notgenerally start executing at main. They start executing in a function called _start, which comes from crt1.oor similar ("C Runtime startup"). Thatfile is part of libc, and it arranges for various initializations, required for the proper start up of your application.

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

Your program actually doesn't require anythingfrom libc, which is why you were able to link it with ld.

您的程序实际上不需要来自 的任何内容libc,这就是您能够将它与ld.

However, consider what happens after your mainreturns. Normally, the code in crt1.owill execute (equivalent of) exit(main(argc, argv));. Since you linked without crt1.o, there is nobody to do that final exitfor you, so the code returns to ... undefined location and promptly crashes.

但是,请考虑您main返回后会发生什么。通常,中的代码crt1.o将执行(相当于)exit(main(argc, argv));。由于您没有链接crt1.o,因此没有exit人为您完成最终操作,因此代码返回到...未定义的位置并立即崩溃。

回答by DarkDust

You also need to link the crt1.o(might have a different name, contains the necessary code up until maincan be called) and necessary libraries. GCC also usually needs to link to libgcc.sowhich contains necessary helper functions (for example, when doing 64 bit calculations on a 32 bit system) plus other system libraries. For example, on my Mac, it also needs to link to libSystemwhich also contain the usual C functions like printf. On Linux, that's usually libc.

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

Note that your program cannot directly start with main(as you're trying to do with with ld .. -e main), the entry point needs to set up a few things prior to calling the C function main. That's what the previously mentioned crt1.ois doing. I guess the segmentation fault is a result of this missing setup.

请注意,您的程序不能直接以 with 开头main(就像您尝试使用 with 一样ld .. -e main),入口点需要在调用 C 函数之前进行一些设置main。这就是前面提到的crt1.o正在做的事情。我猜分段错误是这种缺少设置的结果。

To see what GCC is exactly doing on your system, call:

要查看 GCC在您的系统上究竟做了什么,请调用:

##代码##