Unable to run an executable built with NASM

assemblycompilingexecutablelinker

I am attempting to assemble the assembly source file below using the following NASM command:

nasm -f elf -o test.o test.asm

This completes without errors and I then try to link an executable with ld:

ld -m elf_i386 -e main -o test test.o -lc

This also appears to succeed and I then try to run the executable:

$ ./test
bash: ./test: No such file or directory

Unfortunately, it doesn't seem to work. I tried running ldd on the executable:

linux-gate.so.1 =>  (0xf777f000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7598000)
/usr/lib/libc.so.1 => /lib/ld-linux.so.2 (0xf7780000)

I installed the lsb-core package and verified that /lib/ld-linux.so.2 exists. How come I still can't run the executable?

I'm attempting to do this on a machine running the 64-bit edition of Ubuntu 15.04.

The source code:

; This code has been generated by the 7Basic
; compiler <http://launchpad.net/7basic>

extern printf
extern scanf
extern read
extern strlen
extern strcat
extern strcpy
extern strcmp
extern malloc
extern free

; Initialized data

      SECTION .data
s_0 db "Hello, World!",0
printf_i: db "%d",10,0
printf_s: db "%s",10,0
printf_f: db "%f",10,0
scanf_i: db "%d",0
scanf_f: db "%lf",0
; Uninitialized data

      SECTION .bss
v_12 resb 4
v_0  resb 4
v_4  resb 8

      SECTION .text

; Code

global main
  main:
finit
push ebp
mov ebp,esp
push 0
pop eax
mov [v_12], eax
    l_0:
mov eax, [v_12]
push eax
push 5
pop edx
pop eax
cmp eax, edx
jl l_2
push 0
jmp l_3
    l_2:
push 1
    l_3:
pop eax
cmp eax, 0
je l_1
push s_0
push printf_s
call printf
add esp, 8
mov eax, [v_12]
push eax
push 1
pop edx
pop eax
add eax, edx
push eax
pop eax
mov [v_12], eax
jmp l_0
    l_1:
mov esp,ebp
pop ebp
mov eax,0
ret

Here's the output of strings test:

/usr/lib/libc.so.1
libc.so.6
strcpy
printf
strlen
read
malloc
strcat
scanf
strcmp
free
GLIBC_2.0
t'hx
Hello, World!
.symtab
.strtab
.shstrtab
.interp
.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rel.plt
.text
.eh_frame
.dynamic
.got.plt
.data
.bss
test.7b.out
printf_i
printf_s
printf_f
scanf_i
scanf_f
v_12
_DYNAMIC
_GLOBAL_OFFSET_TABLE_
strcmp@@GLIBC_2.0
read@@GLIBC_2.0
printf@@GLIBC_2.0
free@@GLIBC_2.0
_edata
strcat@@GLIBC_2.0
strcpy@@GLIBC_2.0
malloc@@GLIBC_2.0
scanf@@GLIBC_2.0
strlen@@GLIBC_2.0
_end
__bss_start
main

Best Answer

You need to also link start up fragments like crt1.o and others if you want to call libc functions. The linking process can be very complicated, so you'd better use gcc for that.

On amd64 Ubuntu, you can:

sudo apt-get install gcc-multilib
gcc -m32 -o test test.o

You can see files and commands for the link by adding -v option.

Related Question