R Z
R Z

Reputation: 520

ld does not link object file generated by as

I have written a Hello World program in C. I used the command gcc -S -o hello.s hello.c (code was in hello.c) to generate assembly, then used as to assemble it. Finally I linked the object code using ld, but it gave me the following error:

ld: a.out:hello.c:(.text+0xa): undefined reference to `__main'
ld: a.out:hello.c:(.text+0x16): undefined reference to `puts'

The C code was as follows:

#include <stdio.h>
int main(void) {
    printf("Hello world!\n");
} 

I use an Intel Core i3 processor, and used MinGW to compile. My operating system is Windows 7.

This was the generated assembly:

    .file   "hello.c"
    .text
    .def    ___main;    .scl    2;  .type   32; .endef
    .section .rdata,"dr"
LC0:
    .ascii "Hello world!\0"
    .text
    .globl  _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
LFB13:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    call    ___main
    movl    $LC0, (%esp)
    call    _puts
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE13:
    .ident  "GCC: (MinGW.org GCC Build-2) 9.2.0"
    .def    _puts;  .scl    2;  .type   32; .endef

Upvotes: 2

Views: 762

Answers (2)

Maf
Maf

Reputation: 735

These are the steps I generally follow for the manual Build process with either gcc (C) or g++ (C and C):

  1. gcc -E file.c -o file.i
  2. gcc -S file.i -o file.s
  3. gcc -c file.s -o file.o
  4. gcc file.o -o file.out

The the 1st step (Preprocessing) can also be performed with cpp file.c > file.i.

In the 2nd step (Compiling) I sometimes also name the assembly file as .asm instead of .s. .s is traditional for Unix assembler source files, while .asm is traditional for assemblers like NASM. .S source files will get preprocessed and assembled.

In the 3rd step (Assembling) you can also use the assembler directly: as file.s -o file.o. If you used gcc -v -c file.s (verbose), you'd see it was just running as on it.

In the 4th step (Linking) you could also use the ld tool directly, but the right options for paths and libraries depends on the system so it's normally best to let GCC invoke ld for you. With gcc -v, it will show you what options it passed.

Finally, if we have a very simple application where we don't need a tool like Cmake or Bazel, then we can resume the above steps in a single command: gcc file.c -o file.out.

Again, gcc -v will show you the commands it ran to carry out the internal steps, from whatever starting point to wherever you told it to stop. (With the default being to make an executable.)

Upvotes: 2

R Z
R Z

Reputation: 520

Thanks to Nate Eldredge for helping me get the answer.

To link the file produced by as, use gcc -v (file).

Upvotes: 1

Related Questions