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
How to link a C object file with a Assembly Language object file?
提问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.o
or 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 main
returns. Normally, the code in crt1.o
will execute (equivalent of) exit(main(argc, argv));
. Since you linked without crt1.o
, there is nobody to do that final exit
for 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 main
can be called) and necessary libraries. GCC also usually needs to link to libgcc.so
which 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 libSystem
which 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.o
is 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在您的系统上究竟做了什么,请调用:
##代码##