[1;36mFirstly, some background[0m

[1mWhy do we need to calculate the length of a string?[0m

Well sys_write requires that we pass it a pointer to the string we want to 
output in memory and the length in bytes we want to print out. If we were to 
modify our message string we would have to update the length in bytes that we 
pass to sys_write as well, otherwise it will not print correctly.

You can see what I mean using the program in Lesson 2. Modify the message 
string to say 'Hello, brave new world!' then compile, link and run the new 
program. The output will be 'Hello, brave ' (the first 13 characters) because 
we are still only passing 13 bytes to sys_write as its length. It will be 
particularly necessary when we want to print out user input. As we won't know 
the length of the data when we compile our program, we will need a way to 
calculate the length at runtime in order to successfully print it out.

[1;36mWriting our program[0m

To calculate the length of the string we will use a technique called pointer 
arithmetic. Two registers are initialised pointing to the same address in
memory. One register (in this case EAX) will be incremented forward one byte 
for each character in the output string until we reach the end of the string. 
The original pointer will then be subtracted from EAX. This is effectively 
like subtraction between two arrays and the result yields the number of 
elements between the two addresses. This result is then passed to sys_write 
replacing our hard coded count.

The CMP instruction compares the left hand side against the right hand side 
and sets a number of flags that are used for program flow. The flag we're 
checking is the ZF or Zero Flag. When the byte that EAX points to is equal 
to zero the ZF flag is set. We then use the JZ instruction to jump, if the ZF 
flag is set, to the point in our program labeled 'finished'. This is to break 
out of the nextchar loop and continue executing the rest of the program.

[1;36mhelloworld-len.asm[0m

;[1;30m Hello World Program (Calculating string length)[0m
;[1;30m Compile with: nasm -f elf helloworld-len.asm[0m
;[1;30m Link with (64 bit systems require elf_i386 option): ld -m elf_i386 [0m
;[1;30m    helloworld-len.o -o helloworld-len[0m
;[1;30m Run with: ./helloworld-len[0m
 
[1mSECTION[0;37;40m .data
msg     db      'Hello, brave new world!', 0Ah ; we can modify this now without
having to update anywhere else in the program
 
[1mSECTION[0;37;40m .text
global  _start
 
[1m_start[0;37;40m:
 
    mov     ebx, msg        ; [1;30mmove the address of our message string into EBX[0m
    mov     eax, ebx        ; [1;30mmove the address in EBX into EAX as well [0m
                            ; [1;30m(Both now point to the same segment in memory)[0m
 
[1mnextchar[0;37;40m:
    cmp     byte [eax], 0   ; [1;30mcompare the byte pointed to by EAX at this [0m
                            ; [1;30maddress against zero (Zero is an end of string [0m
                            ; [1;30mdelimiter)[0m
    jz      finished        ; [1;30mjump (if the zero flagged has been set) to the [0m
                            ; [1;30mpoint in the code labeled 'finished'[0m
    inc     eax             ; [1;30mincrement the address in EAX by one byte (if [0m
                            ; [1;30mthe zero flagged has NOT been set)[0m
    jmp     nextchar        ; [1;30mjump to the point in the code labeled 'nextchar'[0m
 
[1mfinished[0;37;40m:
    sub     eax, ebx        ; [1;30msubtract the address in EBX from the address[0m
                            ; [1;30min EAX[0m
                            ; [1;30mremember both registers started pointing to the [0m
                            ; [1;30msame address (see line 15)[0m
                            ; [1;30mbut EAX has been incremented one byte for each [0m
                            ; [1;30mcharacter in the message string[0m
                            ; [1;30mwhen you subtract one memory address from [0m
                            ; [1;30manother of the same type[0m
                            ; [1;30mthe result is number of segments between them - [0m
                            ; [1;30min this case the number of bytes[0m
 
    mov     edx, eax        ; [1;30mEAX now equals the number of bytes in our string[0m
    mov     ecx, msg        ; [1;30mthe rest of the code should be familiar now[0m
    mov     ebx, 1
    mov     eax, 4
    int     80h
 
    mov     ebx, 0
    mov     eax, 1
    int     80h
    
[1;32m~$[0;37;40m nasm -f elf helloworld-len.asm 
[1;32m~$[0;37;40m ld -m elf_i386 helloworld-len.o -o helloworld-len 
[1;32m~$[0;37;40m ./helloworld-len 

Hello, brave new world!
