我有这个简单的C源代码:
#include <stdio.h>
extern int Sum(int,int);
int main()
{
int a,b,s;
a=1 , b=2;
s = Sum(a,b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我有这个s.asm定义函数_Sum:
global _Sum
_Sum:
push ebp ; create stack frame
mov ebp, esp
mov eax, [ebp+8] ; grab the first argument
mov ecx, [ebp+12] ; grab the second argument
add eax, ecx ; sum the arguments
pop ebp ; restore the base pointer
ret
Run Code Online (Sandbox Code Playgroud)
现在,我编译.asm使用:
nasm s.asm -f elf -o s.o
Run Code Online (Sandbox Code Playgroud)
并使用以下方法编译和链接.c文件:
gcc s.o test.o -o testapp
Run Code Online (Sandbox Code Playgroud)
这是结果:
/tmp/ccpwYHDQ.o: In function `main':
test.c:(.text+0x29): undefined reference to `Sum'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
那么问题是什么?
我正在使用Ubuntu-Linux
任何帮助将不胜感激,谢谢
[求助]:我用nm检查了test.o文件,它预计会找到符号'Sum'而不是'_Sum',所以改变它解决了问题.
在典型的汇编程序中,标签默认为本地标签.要告诉汇编程序使它们对外部例程可见,您必须添加一个声明,例如:
.globl _Sum
Run Code Online (Sandbox Code Playgroud)
此外,在C中正确声明例程.这不是导致链接错误的原因,但可能导致其他问题:
extern int Sum(int, int);
Run Code Online (Sandbox Code Playgroud)
为了完整起见,感谢评论者:不要覆盖您的目标文件.您可以组装,编译和链接:
nasm s.asm -f elf -o s.o
gcc test.c s.o -o test
Run Code Online (Sandbox Code Playgroud)
(这命名可执行文件"test",您可能必须使用"./test"执行它以区分目录中的"test"和"test"命令.您可能更乐意选择其他名称.)
出于教育目的:如果nm系统上有该工具,请执行该命令nm s.o.它可能会显示如下:
00000000 t _Sum
Run Code Online (Sandbox Code Playgroud)
该t方法是_Sum在代码段的本地标签.(代码部分也称为文本部分,因此是t.)一旦添加.globl声明并组装新源,nm s.o应该显示一个大写T.大写表示标签在外部可见.