The problem is simple: If you compile and take a look at the object file:
$ nasm -felf32 -o main.o main.asm
$ objdump -h main.o
Sections:
Idx Name Siz. VMA LMA File off Algn
0 .text 0000000b 00000000 00000000 00000160 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 my_section 00000006 00000000 00000000 00000170 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
Where's the "CODE" attribute!? This section is not "exectable". If you add this attribute to the section:
...
section my_section exec
...
And compile again, you'll get:
$ nasm -felf32 -o main.o main.asm
$ objdump -h main.o
Sections:
Idx Name Siz. VMA LMA File off Algn
0 .text 0000000b 00000000 00000000 00000160 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 my_section 00000006 00000000 00000000 00000170 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
$ gcc -s -m32 -o main main.o
$ ./main
$ echo $?
1
PS: Ahhhh.. I've changed the code a little:
bits 32
section .text
global main
main:
mov eax, 1
call sum
; Since you are using the main() function, called from crt0.o, the
; end of your program is a simple return.
ret
section my_section exec
sum:
;mov ebx, 1 ; This should be avoided, since EBX should be preserved!
ret
In general, if you are building a standalone program in assembly, avoid using external libraries like libc... But if you still want to use it, you MUST obey the ABI.
The difference:
$ nasm -felf32 -o main.o main.asm # exit with ret
$ gcc -s -m32 main.o -o main
$ nasm -felf32 -o main2.o main2.asm # exit with sys_exit.
$ ld -s -melf_i386 -e main main2.o -o main2
$ ls -goh main*
-rwxr-xr-x 1 14K apr 25 11:40 main
-rwxr-xr-x 1 4,5K apr 25 11:42 main2
...
$ ldd main main2
main:
linux-gate.so.1 (0xf7f7c000)
libc.so.6 => /lib32/libc.so.6 (0xf7d78000)
/lib/ld-linux.so.2 (0xf7f7e000)
main2:
Not a dynamic executable