Search code examples
linuxgccassemblyx86linker-errors

linux assembly "collect2: ld returned 1 exit status"


I entered the source code on a web site of online coding.

But I got error below the source code.

I think I omitted "main".

Since I learned Intel assmbly, I don't know how to fix it.

Could you help me?

Thank you for helping me in advance.

SECTION .DATA
    hello:     db 'Hello world!',10
    helloLen:  equ $-hello

SECTION .TEXT
    GLOBAL _START

_START:


; Write 'Hello world!' to the screen
mov eax,4            ; 'write' system call
mov ebx,1            ; file descriptor 1 = screen
mov ecx,hello        ; string to write
mov edx,helloLen     ; length of string to write
int 80h              ; call the kernel

; Terminate program
mov eax,1            ; 'exit' system call
mov ebx,0            ; exit with error code 0
int 80h              ; call the kernel

/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o: In function _start': (.text+0x18): undefined reference tomain' collect2: ld returned 1 exit status


Solution

  • If you are just using GCC as a linker and don't care about the C runtime then you can exclude it (as Jester pointed out) by passing -nostdlib to gcc . You then need to provide a _start symbol so the code would look like:

    SECTION .DATA
        hello:     db 'Hello world!',10
        helloLen:  equ $-hello
    
    SECTION .TEXT
        GLOBAL _start
    
    _start:
    ; Write 'Hello world!' to the screen
        mov eax,4            ; 'write' system call
        mov ebx,1            ; file descriptor 1 = screen
        mov ecx,hello        ; string to write
        mov edx,helloLen     ; length of string to write
        int 80h              ; call the kernel
    
        ; Terminate program
        mov eax,1            ; 'exit' system call
        mov ebx,0            ; exit with error code 0
        int 80h              ; call the kernel
    

    You'd assemble and link it like this:

    nasm -f elf file.asm
    gcc -m32 -nostdlib -o file file.o
    

    Alternatively you can link directly with ld so you could also do this:

    nasm -f elf file.asm
    ld -melf_i386 -o file file.o
    

    This would generate a 32-bit Linux executable called file

    Using C Library/runtime

    Although I don't think the following is what you intended, someone may find the following information useful:

    You can use GCC and have the C library available to your assembly code by renaming _START to main. The C runtime contains an entry point called _start that handles initialization and then calls a function called main. You can take advantage of the C library but main has to setup the stack frame correctly and properly clean it up and return when finished since main will be treated as a C function. The code would look something like this:

    EXTERN printf    ; Tell the assembler printf is provided outside our file
    
    SECTION .DATA
        hello:     db 'Hello world!',10,0 ; Null terminate for printf
        helloLen:  equ $-hello-1          ; Exclude null by reducing len by 1
    
    SECTION .TEXT
        GLOBAL main
    
    ; main is now a C function
    main:
        push ebp              ; Setup stack frame
        mov  ebp, esp
        push ebx              ; We need to preserve EBX (C Calling convention)
    
        ; Write 'Hello world!' to the screen
        mov eax,4            ; 'write' system call
        mov ebx,1            ; file descriptor 1 = screen
        mov ecx,hello        ; string to write
        mov edx,helloLen     ; length of string to write
        int 80h              ; call the kernel
    
        ; Write 'Hello World!' with C printf
        push hello           ; push the address of string to print
        call printf          ; call printf in C library
        add esp, 4           ; Restore stack pointer
                             ; push hello pushed 4 bytes on stack
    
        mov  eax, 0x0        ; Return value of 0
        pop  ebx             ; Restore EBX
        leave
        ret                  ; Return to C runtime which will cleanup and exit
    

    This example uses both int 0x80 system call to write standard output, and uses C printf to do the same. You can assemble and link to an executable called file with:

    nasm -f elf file.asm
    gcc -m32 -o file file.o