从C源代码调用程序集例程

hsh*_*hab 3 c assembly

我有这个简单的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',所以改变它解决了问题.

Eri*_*hil 7

在典型的汇编程序中,标签默认为本地标签.要告诉汇编程序使它们对外部例程可见,您必须添加一个声明,例如:

.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.大写表示标签在外部可见.