简体   繁体   English

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

[英]How to call c functions that call c standard library in nasm?

First I want to clarify that I know this question might have been answered hundreds of times. 首先,我想澄清一下,我知道这个问题可能已经回答了数百次。 However after hours of Google search I simply couldn't find anything that's exactly what I want. 但是,经过数小时的Google搜索,我根本找不到我想要的任何东西。 Also even though I've been writing c programs for quite a while, I'm kind of new to nasm and ld. 即使我已经写了很长时间的c程序,我还是nasm和ld的新手。 So I would really appreciate it if I can get a simple answer without having to read a whole nasm/ld tutorial or the complete manual. 因此,如果能得到一个简单的答案而不必阅读整个nasm / ld教程或完整的手册,我将不胜感激。

What I want to do is: 我想做的是:
say I have a function written in c that calls some function in the c standard library: 说我有一个用c编写的函数,该函数调用c标准库中的某些函数:

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

I want to call this function in nasm so I tried this: 我想在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

Then I tried to compile them and run: 然后,我尝试编译它们并运行:

[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

I didn't get any errors but apparently I couldn't run the executable output file. 我没有收到任何错误,但是显然我无法运行可执行输出文件。

If the c function doesn't call any library functions then the code above can be compiled and it will run without any problems. 如果c函数未调用任何库函数,则可以编译以上代码,并且该代码将运行而没有任何问题。 I also figured out a way to call library functions directly in nasm and use gcc to produce the final executable file. 我还想出了一种直接在nasm中调用库函数并使用gcc生成最终可执行文件的方法。 But none of them is exactly what I want. 但是它们都不是我想要的。

EDIT: 编辑:
1. I'm running 64-bit Ubuntu but I'm trying to write 32-bit programs so I used flags like -m32 and -melf_i386. 1.我正在运行64位Ubuntu,但是我试图编写32位程序,因此我使用了-m32和-melf_i386之类的标志。
2. Output of file * : 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. I really have no idea of how to tell ld to include the c standard library. 3.我真的不知道如何告诉ld包括c标准库。 I found something like -lglibc or -lc in some other posts. 我在其他一些帖子中找到了-lglibc或-lc之类的东西。 -lgibc doesn't work and -lc seems to be able to get rid of all errors and I probably thought it worked at first but maybe that's the problem since it probably doesn't link the correct library. -lgibc不起作用,并且-lc似乎能够摆脱所有错误,我可能以为它一开始就起作用了,但也许是问题所在,因为它可能未链接正确的库。

UPDATE UPDATE
Adding -I/lib32/ld-linux.so.2 to the ld command solved my problem. -I/lib32/ld-linux.so.2ld命令解决了我的问题。
Below are commands to compile/assemble/link and run the program: 以下是编译/汇编/链接并运行程序的命令:

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

The C library provides code using the _start interface that starts the C runtime, calls main(), and shuts the runtime down. C库使用_start接口提供代码,该接口启动C运行时,调用main()并关闭运行时。 Hence if you intend to use the C library in your program you must not use the _start interface but provide a main() function. 因此,如果您打算在程序中使用C库,则不得使用_start接口,而应提供main()函数。

This is the correct way to do it: 这是正确的方法:

; main.asm
global main
extern foo

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

    xor eax, eax
    ret

Build with: 构建:

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

Two remarks: 两句话:

  • main() returns, instead of doing an exit system call, to allow the C runtime shutdown code to run. main()返回而不是执行退出系统调用,以允许C运行时关闭代码运行。
  • gcc is used for linking. gcc用于链接。 Internally gcc invokes ld with the appropriate parameters to link with the C library. 在内部,gcc用适当的参数调用ld以与C库链接。 These are platform specific and subject to change. 这些是特定于平台的,随时可能更改。 Hence, don't use ld for this. 因此,请勿为此使用ld。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM