使用汇编函数编译C程序,反之亦然

时间:2014-04-03 20:48:05

标签: c linux assembly x86

我的程序出了问题。当我尝试使用这一行用汇编函数编译我的C程序时:

gcc -o program factarial.c

我得到了这个,我不知道为什么:

/tmp/ccFKqbDP.o: In function `main':
factarial.c:(.text+0x11): undefined reference to `factarial_asm'
collect2: ld returned 1 exit status

这是我的C代码:

#include <stdio.h>

extern void factarial_asm();

int main ()
{
 factarial_asm (5);
 return 0;
}

这是汇编代码:

.data
.text
.global _main
.type factarial_asm, @function

factarial_asm:
    pushl %ebp
    movl %esp, %ebp
    movl 8(%ebp), %eax
    cmpl $1, %eax
je koniec
    decl %eax
    pushl %eax
call factarial_asm
    movl 8(%ebp), %ebx
    mull %ebx
koniec:
leave
ret

此外,当我尝试使用此行编译带有C函数的asm代码时:

gcc -o program factarial.s

我遇到了这个问题:

/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
/tmp/ccWCmTBe.o: In function `main':
(.text+0x3): undefined reference to `factarial'
collect2: ld returned 1 exit status

这是我的asm代码:

SYSEXIT = 1
EXIT_SUCC = 0
SYSWRITE = 4
SYSCALL = 0x80
SYSREAD = 3

.align 32
.text
.global _main
main:

pushl $5
call factarial

movl $SYSEXIT, %eax
movl $EXIT_SUCC, %ebx
int $SYSCALL

我的C代码:

#include <stdio.h>

int factarial(int n)
{
    if(n == 0) return 1;
    else       return n * factarial(n - 1);
}

我知道这是很多问题,但到目前为止,我正在准备编译器和ld链接器,所以我不知道如何使用gcc。 另外,有人可以帮我准备makefile文件吗?

1 个答案:

答案 0 :(得分:4)

问题是你的每个编译行都试图在没有完整程序的情况下创建你的可执行文件。如果源文件具有不同的扩展名,则会使事情变得复杂。

一个简单的选择是这个命令:gcc -o program factarial.c factarial.s

或者,您可以考虑编译但不链接各个源文件,然后将它们的对象链接在一起以构建可执行文件。假设您的源文件名为a.cb.s,您可以:

gcc -c a.c
gcc -c b.s
gcc -o program a.o b.o

最后(当然与你的问题无关),我相信你要找的是factorial:)


装配中仍然存在问题。首先,我重新创建了您的结果,如下所示:

$ gcc -c factarial.c
$ gcc -c factarial_asm.s
$ gcc -o program factarial.o factarial_asm.o
factarial.o: In function `main':
factarial.c:(.text+0xf): undefined reference to `factarial_asm'
collect2: error: ld returned 1 exit status

接下来,我使用nm命令检查目标文件:

$ nm factarial.o
                 U factarial_asm
0000000000000000 T main
$ nm factarial_asm.o
                 U _main
0000000000000000 t factarial_asm
000000000000001a t koniec

汇编对象的nm输出中有一些有趣的东西。首先,U _main告诉我们main()在该对象中未定义,这意味着我们在链接程序时会发现它。这个文件没有调用main()所以我们真的不应该关心它。这是由.global _main引起的,可以安全地删除。

接下来,factarial_asm的符号是小写t,而不是来自主要C来源的T中的main() ...显示为{{ 1}}表示该符号仅对该源文件是本地的,它不会导出到其他文件。 (在C中,这是tvoid function() {}之间的差异。我们需要通过添加适当的static void function() {}指令来解决这个问题。

在程序集中

汇总:,将.global更改为.global _main