如何调用在nasm中调用c标准库的c函数?

时间:2015-01-17 02:23:51

标签: c gcc assembly nasm ld

首先,我想澄清一下,我知道这个问题可能已被回答了数百次。然而,经过几个小时的谷歌搜索,我根本找不到任何我想要的东西。即使我已经写了很长一段时间的c程序,我对nasm和ld也是新手。所以如果我能得到一个简单的答案而不必阅读完整的nasm / ld教程或完整的手册,我将非常感激。

我想做的是:
说我有一个用c编写的函数调用c标准库中的一些函数:

/* foo.c */
#include <stdio.h>
void foo(int i)
{
    printf("%d\n", i);
}

我想在nasm中调用此函数,所以我尝试了这个:

; main.asm
global _start
extern foo

section .text
_start:
    push 1234567
    call foo
    add esp, 4

    mov eax, 1
    xor ebx, ebx
    int 80h

然后我尝试编译它们并运行:

[user ~/Documents/asm/callc]#make all
nasm main.asm -felf
gcc -c foo.c -o foo.o -m32
ld -o main main.o foo.o -melf_i386 -lc
[user ~/Documents/asm/callc]#ls
foo.c  foo.o  main  main.asm  main.o  Makefile
[user ~/Documents/asm/callc]#./main 
bash: ./main: No such file or directory
[user ~/Documents/asm/callc]#bash main
main: main: cannot execute binary file

我没有收到任何错误,但显然我无法运行可执行输出文件。

如果c函数没有调用任何库函数,则可以编译上面的代码,它将运行没有任何问题。我还想出了一种直接在nasm中调用库函数的方法,并使用gcc生成最终的可执行文件。但它们都不是我想要的。

修改
1.我正在运行64位Ubuntu,但我正在尝试编写32位程序,因此我使用了-m32和-melf_i386之类的标志。
2. file *的输出:

[user ~/Documents/asm/sof]#file *
foo.c:     C source, ASCII text
foo.c~:    empty 
foo.o:     ELF 32-bit LSB  relocatable, Intel 80386, version 1 (SYSV), not stripped
main:      ELF 32-bit LSB  executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
main.asm:  C source, ASCII text
main.asm~: empty 
main.o:    ELF 32-bit LSB  relocatable, Intel 80386, version 1 (SYSV), not stripped
Makefile:  makefile script, ASCII text
Makefile~: makefile script, ASCII text

3。我真的不知道如何告诉ld包含c标准库。我在其他一些帖子中找到了类似-lglibc或-lc的东西。 -lgibc不起作用,-lc似乎能够摆脱所有错误,我可能认为它起初有效,但也许这就是问题,因为它可能没有链接正确的库。

更新
-I/lib32/ld-linux.so.2添加到ld命令解决了我的问题 下面是编译/汇编/链接和运行程序的命令:

nasm main.asm -felf
gcc -c foo.c -o foo.o -m32
ld -o main main.o foo.o -melf_i386 -lc -I/lib32/ld-linux.so.2
./main

1 个答案:

答案 0 :(得分:3)

C库使用_start接口提供代码,该接口启动C运行时,调用main()并关闭运行时。因此,如果您打算在程序中使用C库,则不得使用_start接口,而是提供main()函数。

这是正确的方法:

; main.asm
global main
extern foo

section .text
main:
    push 1234567
    call foo
    add esp, 4

    xor eax, eax
    ret

构建:

nasm -f elf32 -o main.o main.asm
gcc -m32 -o foo.o -c foo.c
gcc -m32 -o main main.o foo.o

两个评论:

  • main()返回而不是执行退出系统调用,以允许C运行时关闭代码运行。
  • gcc用于链接。内部gcc使用适当的参数调用ld以与C库链接。这些是特定于平台的,可能会有所变化。因此,不要使用ld。