Linking an assembler program: error “undefined reference to `printf'”

ⅰ亾dé卋堺 提交于 2019-12-03 17:18:27

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

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

  1. use the ld linker but tell it to use c lib via lc options. i.e: ld -ld -o 0_strange_calc 0_strange_calc.o -lc. More info can be found here

  2. use 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!