Some more background

After successfully learning how to execute a system call in Lesson 1 we now 
need to learn about one of the most important system calls in the kernel, 
sys_exit.

Notice how after our 'Hello, world!' program ran we got a Segmentation fault? 
Well, computer programs can be thought of as a long strip of instructions that
are loaded into memory and divided up into sections (or segments). This 
general pool of memory is shared between all programs and can be used to store
variables, instructions, other programs or anything really. Each segment is 
given an address so that information stored in that section can be found 
later.

To execute a program that is loaded in memory, we use the global label _start: 
to tell the operating system where in memory our program can be found and 
executed. Memory is then accessed sequentially following the program logic 
which determines the next address to be accessed. The kernel jumps to that 
address in memory and executes it.

It's important to tell the operating system exactly where it should begin 
execution and where it should stop. In Lesson 1 we didn't tell the kernel 
where to stop execution. So, after we called sys_write the program continued 
sequentially executing the next address in memory, which could have been 
anything. We don't know what the kernel tried to execute but it caused it to 
choke and terminate the process for us instead - leaving us the error message
of 'Segmentation fault'. Calling sys_exit at the end of all our programs will
mean the kernel knows exactly when to terminate the process and return memory
back to the general pool thus avoiding an error.

Writing our program

Sys_exit has a simple function definition. In the Linux System Call Table it
is allocated OPCODE 1 and is passed a single argument through EBX.

In order to execute this function all we need to do is:

    Load EBX with 0 to pass zero to the function meaning 'zero errors'.
    Load EAX with 1 to call sys_exit.
    Then request an interrupt on libc using INT 80h.

We then compile, link and run it again.

; Hello World Program - asmtutor.com
; Compile with: nasm -f elf helloworld.asm
; Link with (64 bit systems require elf_i386 option):
     ld -m elf_i386 helloworld.o -o helloworld
; Run with: ./helloworld
 
SECTION .data
msg     db      'Hello World!', 0Ah
 
SECTION .text
global  _start
 
_start:
 
    mov     edx, 13
    mov     ecx, msg
    mov     ebx, 1
    mov     eax, 4
    int     80h
 
    mov     ebx, 0      ; return 0 status on exit - 'No Errors'
    mov     eax, 1      ; invoke SYS_EXIT (kernel opcode 1)
    int     80h
    


Now if you compile and execute the program it will exit normaly.

~$ nasm -f elf helloworld.asm 
~$ ld -m elf_i386 helloworld.o -o helloworld 
~$ ./helloworld 
Hello World!
