Skip to content
Advertisement

How to link C language libraries?

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

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement