External include files allow us to move code from our program and put it into
separate files. This technique is useful for writing clean, easy to maintain 
programs. Reusable bits of code can be written as subroutines and stored in 
separate files called libraries. When you need a piece of logic you can 
include the file in your program and use it as if they are part of the same 
file.

In this lesson we will move our string length calculating subroutine into an 
external file. We fill also make our string printing logic and program exit 
logic a subroutine and we will move them into this external file. Once it's 
completed our actual program will be clean and easier to read.

We can then declare another message variable and call our print function 
twice in order to demonstrate how we can reuse code.

functions.asm
;------------------------------------------
; int slen(String message)
; String length calculation function
slen:
    push    ebx
    mov     ebx, eax
 
nextchar:
    cmp     byte [eax], 0
    jz      finished
    inc     eax
    jmp     nextchar
 
finished:
    sub     eax, ebx
    pop     ebx
    ret
 
 
;------------------------------------------
; void sprint(String message)
; String printing function
sprint:
    push    edx
    push    ecx
    push    ebx
    push    eax
    call    slen
 
    mov     edx, eax
    pop     eax
 
    mov     ecx, eax
    mov     ebx, 1
    mov     eax, 4
    int     80h
 
    pop     ebx
    pop     ecx
    pop     edx
    ret
 
helloworld.asm
;------------------------------------------
; void exit()
; Exit program and restore resources
quit:
    mov     ebx, 0
    mov     eax, 1
    int     80h
    ret
    
    
; Hello World Program (External file include)
; Compile with: nasm -f elf helloworld-inc.asm
; Link with (64 bit systems require elf_i386 option): 
;   ld -m elf_i386 helloworld-inc.o -o helloworld-inc
; Run with: ./helloworld-inc
 
%include        'functions.asm'         ; include our external file
 
SECTION .data
                ; our first message string
msg1    db      'Hello, brave new world!', 0Ah              
                ; our second message string
msg2    db      'This is how we recycle in NASM.', 0Ah      
 
SECTION .text
global  _start
 
_start:
    ; move the address of our first message string into EAX
    mov     eax, msg1       
    call    sprint          ; call our string printing function
 
    ; move the address of our second message string into EAX
    mov     eax, msg2       
    call    sprint          ; call our string printing function
 
    call    quit            ; call our quit function
    

~$ nasm -f elf helloworld-inc.asm 
~$ ld -m elf_i386 helloworld-inc.o -o helloworld-inc 
~$ ./helloworld-inc 
Hello, brave new world! 
This is how we recycle in NASM. 
This is how we recycle in NASM.
