Reputation: 357
First I want to clarify that I know this question might have been answered hundreds of times. However after hours of Google search I simply couldn't find anything that's exactly what I want. Also even though I've been writing c programs for quite a while, I'm kind of new to nasm and ld. So I would really appreciate it if I can get a simple answer without having to read a whole nasm/ld tutorial or the complete manual.
What I want to do is:
say I have a function written in c that calls some function in the c standard library:
/* foo.c */
#include <stdio.h>
void foo(int i)
{
printf("%d\n", i);
}
I want to call this function in nasm so I tried this:
; main.asm
global _start
extern foo
section .text
_start:
push 1234567
call foo
add esp, 4
mov eax, 1
xor ebx, ebx
int 80h
Then I tried to compile them and run:
[user ~/Documents/asm/callc]#make all
nasm main.asm -felf
gcc -c foo.c -o foo.o -m32
ld -o main main.o foo.o -melf_i386 -lc
[user ~/Documents/asm/callc]#ls
foo.c foo.o main main.asm main.o Makefile
[user ~/Documents/asm/callc]#./main
bash: ./main: No such file or directory
[user ~/Documents/asm/callc]#bash main
main: main: cannot execute binary file
I didn't get any errors but apparently I couldn't run the executable output file.
If the c function doesn't call any library functions then the code above can be compiled and it will run without any problems. I also figured out a way to call library functions directly in nasm and use gcc to produce the final executable file. But none of them is exactly what I want.
EDIT:
1. I'm running 64-bit Ubuntu but I'm trying to write 32-bit programs so I used flags like -m32 and -melf_i386.
2. Output of file *
:
[user ~/Documents/asm/sof]#file *
foo.c: C source, ASCII text
foo.c~: empty
foo.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
main: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
main.asm: C source, ASCII text
main.asm~: empty
main.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
Makefile: makefile script, ASCII text
Makefile~: makefile script, ASCII text
3. I really have no idea of how to tell ld to include the c standard library. I found something like -lglibc or -lc in some other posts. -lgibc doesn't work and -lc seems to be able to get rid of all errors and I probably thought it worked at first but maybe that's the problem since it probably doesn't link the correct library.
UPDATE
Adding -I/lib32/ld-linux.so.2
to the ld
command solved my problem.
Below are commands to compile/assemble/link and run the program:
nasm main.asm -felf
gcc -c foo.c -o foo.o -m32
ld -o main main.o foo.o -melf_i386 -lc -I/lib32/ld-linux.so.2
./main
Upvotes: 3
Views: 5306
Reputation:
The C library provides code using the _start interface that starts the C runtime, calls main(), and shuts the runtime down. Hence if you intend to use the C library in your program you must not use the _start interface but provide a main() function.
This is the correct way to do it:
; main.asm
global main
extern foo
section .text
main:
push 1234567
call foo
add esp, 4
xor eax, eax
ret
Build with:
nasm -f elf32 -o main.o main.asm
gcc -m32 -o foo.o -c foo.c
gcc -m32 -o main main.o foo.o
Two remarks:
Upvotes: 4