1

I have started to learn assembly language and currently making a simple asm program to call printf function in C in stdio.h.
I am unable to link the object file properly after assembling. The problem I am facing is

undefined reference to printf

After browsing other questions with similar problems on SO, I tried

nasm -f elf -l call.lst call.asm  
gcc -o call call.o  

After doing this, I get the error:

i386 architecture of input file call.o is compatible with x86_64 output.

How should I properly link the file? Currently, I am doing the following :-

nasm -f elf call.asm
ld -m elf_i386 -s -o call call.o

What changes should I make to the above line ?

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
Pratik Singhal
  • 6,283
  • 10
  • 55
  • 97

1 Answers1

4

If you're writing 32-bit assembly code, you need to tell GCC this:

$ gcc -m32 -o call call.o

Alternatively, if you're writing 64-bit assembly (with [BITS 64]), then you would:

$ nasm -f elf64 -l call.lst call.asm
$ gcc -m64 -o call call.o

This just worked for me:

test.s

[BITS 32]

extern printf

global main
main:
    push    message
    call    printf
    add     esp, 4
    xor     eax, eax
    ret

message:
    db "hello",0xA,0

Build

nasm -f elf test.s
gcc -m32 -o calltest test.o
./calltest
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • +1 Hey Jonathan, its been forever since I hand-rolled asm modules calling C. Does the C-runtime lib for most vendors still use leading underscores on their functions? – WhozCraig May 25 '14 at 06:31
  • @WhozCraig Good question. I should be able to tell you in a minute - I'm trying this now. – Jonathon Reinhart May 25 '14 at 06:31
  • I only ask because of the id in the OP's posted undef-ref messaging. – WhozCraig May 25 '14 at 06:32
  • Thanks for the quick reply, but assembling it this way is still giving errors like :- `cannot find crt1.o: No such file or directory`, `Cannot find crti.o, No such file or directory`. and others – Pratik Singhal May 25 '14 at 06:33
  • 1
    Do you have the 32-bit version of `libc` installed? On a yum-based system: `sudo yum install glibc.i686 glibc-devel.i686` – Jonathon Reinhart May 25 '14 at 06:34
  • No, installing it currently and will then reassemble – Pratik Singhal May 25 '14 at 06:36
  • After installing, it is still giving the same error – Pratik Singhal May 25 '14 at 06:38
  • Are you using `nasm -f elf`, and `gcc -m32` ? – Jonathon Reinhart May 25 '14 at 06:38
  • I am doing as you told, but it's not working. Can you tell me how do I confirm whether 32 bit libc is installed or not? – Pratik Singhal May 25 '14 at 06:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/54373/discussion-between-jonathon-reinhart-and-ps06756). – Jonathon Reinhart May 25 '14 at 06:48
  • @WhozCraig No underscores needed :-) – Jonathon Reinhart May 25 '14 at 07:00
  • @JonathonReinhart good to know. Unfortunately, a mach-o spin still does use them. my mac isn't as direct as a deb box in doing this either. Thanks for the info, btw. – WhozCraig May 25 '14 at 07:07
  • @WhozCraig For that, NASM offers the `--prefix` option, which will *" prepend ... the given argument to all global or extern variables."* [(Manual)](http://www.nasm.us/doc/nasmdoc2.html) – Jonathon Reinhart May 25 '14 at 07:11
  • Well bless your heart. Thanks!. I don't suppose you know the System V ABI for x86 fast-call register loading off the top of your head. I'll be even more impressed than I already am =P – WhozCraig May 25 '14 at 07:13
  • (from the top of my head) `eax, ecx, edx, [stack]` if my memory serves me correctly. EDIT: A quick test in GCC shows it's just `ecx, edx, [stack]` – Jonathon Reinhart May 25 '14 at 07:18
  • @WhozCraig No problem. FYI: I put `__attribute__((fastcall))` on an extern function prototype which took 5 parameters and called it. I compiled it with `gcc -c fastcall.c` and looked at the output with `objdump -M intel -d fastcall.o`. Thanks for the mini-challenge! – Jonathon Reinhart May 25 '14 at 07:27