问题
I am interested in executing a function which is written in C language:-
//filename "CLang.c"
#include<stdio.h>
void fun() {
printf("Hello World");
}
I want to call this fun()
through assembly language which i have written:- (NASM 64bit)
; filename "MyASM.asm"
section .data
section .bss
section .text
global _start
_start:
call fun
mov rax,60 ; exit
mov rdi,1
syscall
I have created object file by using these commands nasm -f elf64 MyAsm.asm
and gcc -c CLang.c
.
When I merge these two file with gcc gcc MyASM.o CLang.o
i get an error as
MyASM.o: In function `_start':
MyASM.asm:(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o:(.text+0x0): first defined here
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
I didn't understand why it says as multiple definition of _start
I have written only one _start ???
I have no clue how to attach only gcc libraries with MyASM.o ???
回答1:
The error you are getting is because you are defining _start
and because you are compiling and linking with the C library (using GCC). The C library defines a _start
label that initializes the C run-time. The two _start
labels are the reason for the linker complaining about _start
being redefined. The C startup code in the library is responsible for transferring control to main
when it has properly initialized everything.
If you are using the C library (GLIBC) functions either directly or indirectly you need to ensure the C library is properly initialized by linking in its library and its run-time environment. By default this is something GCC does for you (it can be overridden).
You can define main
as an assembly language function like this:
extern fun
section .text
global main
main:
push rbp ; Pushing a 64-bit register aligns stack back on 16-byte
; boundary so the call to `fun` has proper 16-byte
; alignment per the AMD64(X86-64) System V ABI.
call fun
xor eax, eax ; RAX=0 (main's return value)
pop rbp ; Restore the stack
ret ; Return back to C startup code which will exit for us.
You should be able to use your existing commands to assemble with NASM, compile with GCC, and link with GCC.
You may find some additional information about _start
/main
and the C runtime that is somewhat related here and information on the -nostartfiles
option in the answers to this other question.
There is more information on stack alignment requirements in the answers to this Stackoverflow question
回答2:
In general, libraries are created from many library source files, and are either built as archive files (libmine.a) that are statically linked into executables that use them, or as shared object files (libmine.so) that are dynamically linked into executables that use them. To link in libraries of these types, use the gcc command line options -L for the path to the library files and -l to link in a library (a .so or a .a):
-L{path to file containing library} -l${library name}
For example, if I have a library named libmine.so in /home/newhall/lib/ then I'd do the following to link it into my program:
$ gcc -o myprog myprog.c -L/home/newhall/lib -lmine
You may also need to specify and include path so the compiler can find the library header file: -I /home/newhall/include If you create your own shared object files and do not install them in /usr/lib, then you need to set your LD_LIBRARY_PATH environment variable so that the runtime linker can find them and load them at run time. For example, if I put my .so files in a directory named lib in my home directory, I'd set my LD_LIBRARY_PATH enviroment to the following:
# if running bash:
export LD_LIBRARY_PATH=/home/newhall/lib:$LD_LIBRARY_PATH
# if running tcsh:
setenv LD_LIBRARY_PATH /home/newhall/lib:$LD_LIBRARY_PATH
来源:https://stackoverflow.com/questions/56464959/how-to-link-c-language-libraries