Linking an assembler program: error "undefined reference to `printf'"
Solution 1
You have a couple of options
- Use LD to link to a final executable
- Use GCC to link to a final executable
Using LD Method
Your command lines use LD, unfortunately that presents a number of problems. The first:
ld: i386 architecture of input file `0_strange_calc.o' is incompatible with i386:x86-6
You are on 64-bit Debian, trying to produce a 32-bit executable. -f elf
on the NASM command line generates 32-bit ELF (-f elf64
generate 64 bit objects). Your LD command line is by default trying to generate a 64-bit executable thus the error above is given. You can force LD to generate a 32-bit executable by adding the -m elf_i386
option to LD's command line.
ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0
You should tell LD that your entry point is main . LD by default looks for an entry point of _start. You can add -e main
to the LD command line to resolve that.
Errors like this suggest you need the C library (where printf exists):
0_strange_calc.asm:(.text+0x8): undefined reference to `printf'
Since your code doesn't use printf directly I can only assume that is required by the functions in training.s
. In order to link in the C library you will need to add it after the .o
files in your command line. You can do this with -lc
on your LD command line. You'll also need to tell LD specifically what dynamic linker library you will need to use (In this case a 32-bit one). In a Debian environment that will usually look like: -dynamic-linker /lib/ld-linux.so.2
So your NASM and LD lines should look like this:
nasm -f elf -g 0_strange_calc.asm
ld -melf_i386 -e main -dynamic-linker /lib/ld-linux.so.2 -o 0_strange_calc 0_strange_calc.o -lc
Using GCC Method
You can simplify linking to the C library by using GCC to link you your object file to an executable. To build a 32-bit executable you could use:
nasm -f elf -g 0_strange_calc.asm
gcc -m32 0_strange_calc.o -o 0_strange_calc
The C library and runtime has a _start method that does C startup initialization and in turn calls a function called main which happens to be the function in your assembly file. -m32
tells GCC you are also linking to a 32-bit executable.
Special Considerations
You may also need to to install the Multlilib versions of gcc (and g++ if you want to) so that you can properly build and run 32-bit applications on 64-bit Debian using the appropriate C libraries. That can be done with this command line:
apt-get install gcc-multilib g++-multilib
On Ubuntu based systems you'd need to use:
sudo apt-get install gcc-multilib g++-multilib
Solution 2
Note that the problem is not the asm
code but a missing imported function. If you read
training.s you will see the definition of printeax
and other methods as well. Moreover you will see that some of those method use external function
like printf
which is of course not asm
function but some imported language lib
BITS 32
extern printf
extern exit
extern scanf
extern read
So in order to make it work - i.e to find those external libs ( you have also warning there that you should handle but this is out of this scope). You need to use the linker properly. According to Frank
at the nasm board you have two options
use the
ld
linker but tell it to usec
lib vialc
options. i.e:ld -ld -o 0_strange_calc 0_strange_calc.o -lc
. More info can be found hereuse the
gcc
linker.
P.S
Note that also the code uses 32bit
which on your computer produce a warning as you can use 64 bit
and you use elf
flag. More on it you can find at the nasm docs
Kaka
Updated on December 20, 2020Comments
-
Kaka over 3 years
I'm trying to compile this x86 assembly code on x64 Debian :
BITS 32 %include 'training.s' global main extern exit ; =============================================== section .text main: ; The program begins here: call read_hex mov edx,eax call read_hex add eax,edx add eax,eax inc eax call print_eax ; Exit the process: push 0 call exit
I'm getting these errors:
~$nasm -f elf -g 0_strange_calc.asm && ld -o 0_strange_calc 0_strange_calc.o ld: i386 architecture of input file `0_strange_calc.o' is incompatible with i386:x86-64 output ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0 0_strange_calc.o:training.s:25: undefined reference to `printf' 0_strange_calc.o:training.s:35: undefined reference to `printf' 0_strange_calc.o:training.s:45: undefined reference to `printf' 0_strange_calc.o:training.s:56: undefined reference to `read' 0_strange_calc.o:training.s:77: undefined reference to `scanf' 0_strange_calc.o:training.s:97: undefined reference to `scanf' 0_strange_calc.o:training.s:108: undefined reference to `printf' 0_strange_calc.o:training.s:129: undefined reference to `printf' 0_strange_calc.o:training.s:137: undefined reference to `printf' 0_strange_calc.o:0_strange_calc.asm:50: undefined reference to `exit' ~$ yasm -f elf64 0_strange_calc.asm ~$ gcc -m32 -nostdlib -nostdinc 0_strange_calc.o -o 0_strange_calc /usr/bin/ld: i386:x86-64 architecture of input file `0_strange_calc.o' is incompatible with i386 output /usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 00000000080480c0 0_strange_calc.o: In function `no symbol': 0_strange_calc.asm:(.text+0x8): undefined reference to `printf' 0_strange_calc.asm:(.text+0x19): undefined reference to `printf' 0_strange_calc.asm:(.text+0x2a): undefined reference to `printf' 0_strange_calc.asm:(.text+0x39): undefined reference to `read' 0_strange_calc.asm:(.text+0x5b): undefined reference to `scanf' 0_strange_calc.asm:(.text+0x7a): undefined reference to `scanf' 0_strange_calc.asm:(.text+0x89): undefined reference to `printf' 0_strange_calc.asm:(.text+0xa8): undefined reference to `printf' 0_strange_calc.asm:(.text+0xb9): undefined reference to `printf' 0_strange_calc.o: In function `main': 0_strange_calc.asm:(.text+0xdb): undefined reference to `exit' collect2: error: ld returned 1 exit status
This is my dump of 0_strange_calc.o:
~$ objdump -M intel -d 0_strange_calc.o 0_strange_calc.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main-0xc2>: 0: 60 (bad) 1: 50 push rax 2: 68 00 00 00 00 push 0x0 7: e8 00 00 00 00 call c <main-0xb6> c: 83 c4 08 add esp,0x8 f: 61 (bad) 10: c3 ret 11: 60 (bad) 12: 50 push rax 13: 68 00 00 00 00 push 0x0 18: e8 00 00 00 00 call 1d <main-0xa5> 1d: 83 c4 08 add esp,0x8 20: 61 (bad) 21: c3 ret 22: 60 (bad) 23: b8 00 00 00 00 mov eax,0x0 28: 50 push rax 29: e8 00 00 00 00 call 2e <main-0x94> 2e: 83 c4 04 add esp,0x4 31: 61 (bad) 32: c3 ret 33: 60 (bad) 34: 51 push rcx 35: 57 push rdi 36: 6a 00 push 0x0 38: e8 00 00 00 00 call 3d <main-0x85> 3d: 83 c4 0c add esp,0xc 40: 31 d2 xor edx,edx 42: c6 04 07 00 mov BYTE PTR [rdi+rax*1],0x0 46: 61 (bad) 47: c3 ret 48: 55 push rbp 49: 89 e5 mov ebp,esp 4b: 83 ec 04 sub esp,0x4 4e: 53 push rbx 4f: 51 push rcx 50: 52 push rdx 51: 8d 5d fc lea ebx,[rbp-0x4] 54: 53 push rbx 55: 68 00 00 00 00 push 0x0 5a: e8 00 00 00 00 call 5f <main-0x63> 5f: 83 c4 08 add esp,0x8 62: 8b 03 mov eax,DWORD PTR [rbx] 64: 5a pop rdx 65: 59 pop rcx 66: 5b pop rbx 67: c9 leave 68: c3 ret 69: 55 push rbp 6a: 89 e5 mov ebp,esp 6c: 83 ec 04 sub esp,0x4 6f: 8d 5d fc lea ebx,[rbp-0x4] 72: 60 (bad) 73: 53 push rbx 74: 68 00 00 00 00 push 0x0 79: e8 00 00 00 00 call 7e <main-0x44> 7e: 83 c4 08 add esp,0x8 81: 61 (bad) 82: 8b 03 mov eax,DWORD PTR [rbx] 84: c9 leave 85: c3 ret 86: 60 (bad) 87: 56 push rsi 88: e8 00 00 00 00 call 8d <main-0x35> 8d: 83 c4 04 add esp,0x4 90: 61 (bad) 91: c3 ret 92: 60 (bad) 93: b9 20 00 00 00 mov ecx,0x20 98: d1 c0 rol eax,1 9a: 89 c2 mov edx,eax 9c: 83 e2 01 and edx,0x1 9f: 51 push rcx a0: 50 push rax a1: 52 push rdx a2: 68 00 00 00 00 push 0x0 a7: e8 00 00 00 00 call ac <main-0x16> ac: 83 c4 08 add esp,0x8 af: 58 pop rax b0: 59 pop rcx b1: e2 e5 loop 98 <main-0x2a> b3: 68 00 00 00 00 push 0x0 b8: e8 00 00 00 00 call bd <main-0x5> bd: 83 c4 04 add esp,0x4 c0: 61 (bad) c1: c3 ret 00000000000000c2 <main>: c2: e8 81 ff ff ff call 48 <main-0x7a> c7: 89 c2 mov edx,eax c9: e8 7a ff ff ff call 48 <main-0x7a> ce: 01 d0 add eax,edx d0: 01 c0 add eax,eax d2: 40 e8 28 ff ff ff rex call 0 <main-0xc2> d8: 6a 00 push 0x0 da: e8 00 00 00 00 call df <main+0x1d>
It seems to have been converted successfully in x64 asm, other simple code I had compiled and linked without problems. What am I doing wrong? And how can I fix it?
-
Kaka over 8 yearsIt seems to compile, but it doesn't generate any output file. I'm using this commands: ` $ nasm -f elf -g 0_strange_calc.asm ` ` ~$ ld -melf_i386 -e main -dynamic-linker /lib/ld-linux.so.2 -o strange_calc 0_strange_calc.o -lc`
-
Michael Petch over 8 years@Kaka The original command line I gave (I fixed it already) output to a file called
strange_calc
(not0_strange_calc
). That was an error on my part. Just change it told -melf_i386 -e main -dynamic-linker /lib/ld-linux.so.2 -o 0_strange_calc 0_strange_calc.o -lc
(The output file was only thing that was wrong) -
Kaka over 8 yearsYes, it generated a file called "strange_calc". Now I manage to run it. The app doesn't seem to give any output, but I suppose this is the expected result. Thank you
-
Michael Petch over 8 yearsIf it isn't printing probably a problem with your code. I don't know how
print_eax
works since it isn't part of the code given. But if you are linking and get an exectuable, printing being incorrect would likely be better asked in another question if you can't resolve it. -
Kaka over 8 yearsI just needed to input two numbers. Works fine.
-
WENDYN about 2 yearsI keep getting
cannot find -lc
withld
, any idea why? Is it possible that it has to do something with me using MinGW toolkit?