I am studying Assembly language using this nasm tutorial. Here is the code that prints a string:
SECTION .data
msg     db      'Hello!', 0Ah
SECTION .text
global  _start
_start:
    mov     ebx, msg
    mov     eax, ebx
    ; calculate number of bytes in string
nextchar:
    cmp     byte [eax], 0
    jz      finished
    inc     eax
    jmp     nextchar
finished:
    sub     eax, ebx    ; number of bytes in eax now 
    mov     edx, eax    ; number of bytes to write - one for each letter plus 0Ah (line feed character)
    mov     ecx, ebx    ; move the memory address of our message string into ecx
    mov     ebx, 1      ; write to the STDOUT file
    mov     eax, 4      ; invoke sys_write (kernel opcode 4)
    int     80h
    mov     ebx, 0      ; no errors
    mov     eax, 1      ; invoke sys_exit (kernel opcode 1)
    int     80h
It works and successfully prints "Hello!\n" to STDOUT. One thing I don't understand: it searches for \0 byte in msg, but we didn't define it. Ideally, the correct message definition should be
msg     db      'Hello!', 0Ah, 0h
How does it successfully get the zero byte at the end of the string?
The similar case is in exercise 7:
; String printing with line feed function
sprintLF:
    call    sprint
 
    push    eax         ; push eax onto the stack to preserve it while we use the eax register in this function
    mov     eax, 0Ah    ; move 0Ah into eax - 0Ah is the ascii character for a linefeed
    push    eax         ; push the linefeed onto the stack so we can get the address
    mov     eax, esp    ; move the address of the current stack pointer into eax for sprint
    call    sprint      ; call our sprint function
    pop     eax         ; remove our linefeed character from the stack
    pop     eax         ; restore the original value of eax before our function was called
    ret                 ; return to our program
It puts just 1 byte: 0Ah into eax without terminating 0h, but the string length is calculated correctly inside sprint. What is the cause?
