5

I have a very simple main.c file:

#include <stdio.h>
int cnt;
extern void increment();
int main()
{
    cnt = 0;
    increment();
    printf("%d\n", cnt);
    return 0;
}

And even simpler hello.asm:

EXTERN cnt
section .text 
global increment 
increment:
  inc dword [cnt]
ret

First I get main.o by typing gcc -c main.c Then I get hello.o -- nasm -f macho hello.asm -DDARWIN And, finally, to get an executable I do ld -o main main.o hello.o -arch i386 -lc and get an error:

ld: warning: -macosx_version_min not specified, assuming 10.10
ld: warning: 
ignoring file main.o, file was built for unsupported file format  (   0xCF 0xFA 0xED 0xFE 0x07 0x00 0x00 0x01 0x03 0x00 0x00 0x00 0x01 0x00 0x00 0x00 ) which is not the architecture being linked (i386): main.o
Undefined symbols for architecture i386:
  "_main", referenced from:
 implicit entry/start for main executable
"cnt", referenced from:
  increment in hello.o
ld: symbol(s) not found for architecture i386

How do I fix this linking error?

theluckyemil
  • 663
  • 1
  • 7
  • 16
  • @EOF because that doesn't work? `gcc` doesn't know to invoke `nasm` – Jester Apr 28 '15 at 18:59
  • @Jester: Yeah, I just realized it's not written in gas assembly... – EOF Apr 28 '15 at 19:00
  • 1
    Do you happen to be on a 64 bit OS? Then do `gcc -m32` for your `main.c`. Along the lines of @EOF's suggestion, you can also use gcc once you got your `hello.o` as: `gcc main.c hello.o` (add `-m32` if necessary). – Jester Apr 28 '15 at 19:00
  • @Jester with -m32 option I don't get file was built for unsupported file format error. But other errors still remain. – theluckyemil Apr 28 '15 at 19:25
  • This might work, try defining `cnt` in the assembly file in a data section like this `cnt dw 0` and make it global like `increment` by adding `global cnt` above it and also remove the `extern cnt` line. Now in the `c` source change `int cnt` to `extern int cnt`, hopefully that should get everything to link properly. – James Apr 28 '15 at 19:35
  • @James changed like you said, but it didn't work. I get the same errors. There is no mistake in the code because on Ubuntu it works fine. – theluckyemil Apr 28 '15 at 20:03

1 Answers1

1
  • Specify architecture (32/64 bit with options m32 or m64)
  • link crt files, these files contain the runtime - that's the code that calls your main function

Modify your asm file:

EXTERN _cnt
section .text
global _increment
_increment:
  inc dword [_cnt]
ret

So the final command lines should be:

gcc -c -m32 main.c
nasm -f macho hello.asm -DDARWIN
ld hello.o main.o /usr/lib/crt1.o  -lc -o main

Check arch and execute:

file main
main: Mach-O executable i386

./main
1
Laser
  • 6,652
  • 8
  • 54
  • 85
  • why do we need an underscore before variable names? – theluckyemil Apr 29 '15 at 17:49
  • @theluckyemil answer is here http://stackoverflow.com/questions/5908568/what-is-the-reason-function-names-are-prefixed-with-an-underscore-by-the-compile – Laser Apr 29 '15 at 19:07