Reputation: 27564
There are only two files, main.c
and kernel.asm
, and I tried to make a program with them using NASM and GCC. contents are as follows:
main.c
#include <stdio.h>
void Print_String() {
printf("Hello World!\n");
}
kernle.asm
extern Print_String
[section .text]
global _start
_start:
call Print_String
Compile and Link:
nasm -f elf -o kernel.o kernel.asm
gcc -c -o main.o main.c
ld -s -lc -o final kernel.o main.o
Then I run the final
file with the command: ./final
, but the result is depressing:
bash: ./final: No such file or directory
However, the current directory does have the file final
, for the command ls
, it displays:
final kernel.asm kernel.o main.c main.o
So why it cannot find the file final
? Is there anything wrong? Any help appreciated!
Upvotes: 3
Views: 1227
Reputation: 11791
Very simple: there is no main()
to call in the program... thus whatever you do, the C-program-startup machinery doesn't get a hold.
Upvotes: 0
Reputation: 3509
It is not that it cannot find it, per se. The error message is somewhat misleading. The dynamic linker cannot resolve its dependencies, and thus your program image is not loadable (and not executable)
The problem is that you are dynamically linking against libc without any other of the paraphernalia to make dynamic linking actually work. Thus you are left with a binary image that cannot be loaded.
You might find that it's easier to statically link against libc. This can be done as follows:
ld -Bstatic -o final kernel.o main.o -lc
Notice you have to move the '-lc' bit after the code module main.o which uses it.
If you try this, you'll get a whole bunch of unresolved symbols. That's because you will also need to link against libgcc and libgcc_eh.
The following got me fairly close (apologies, working on a 64-bit system here):
ld -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/32/ -melf_i386 -Bstatic -lc -o final kernel.o main.o -lc -lgcc -lgcc_eh
This failed for me with
/usr/lib/gcc/x86_64-linux-gnu/4.4.3/32//libgcc_eh.a(unwind-dw2-fde-glibc.o): In function `_Unwind_Find_FDE':
(.text+0x193b): undefined reference to `dl_iterate_phdr'
Which doesn't make much sense. You may have more luck linking 32-bit on a 32-bit system.
Update
Apologies for the ramble above. I had a think about this again, and, of course, it is possible to make dynamic linking work. The missing piece is to specify the dynamic linker:
In my case, this was:
ld -dynamic-linker /lib32/ld-linux.so.2 -melf_i386 -o final kernel.o main.o -lc
So for you the following should work:
ld -dynamic-linker /lib/ld-linux.so.2 -o final kernel.o main.o -lc
Update again
In response to markzar's comment - you have to make a syscall to cleanly exit. This has the effect of doing something similar to exit(0) in C:
mov eax,1 ; Syscall #1
mov ebx,0 ; Return code 0 = success
int 80H
Upvotes: 4
Reputation: 8923
Try this. First change kernel.asm as follows:
extern Print_String
[section .text]
global main
main:
call Print_String
Then use the following commands to create the executable (instead of the linker).
nasm -f elf -o kernel.o kernel.asm
gcc -c -o main.o main.c
gcc -o final kernel.o main.o
Upvotes: 1