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 ???
Advertisement
Answer
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