Simple program to print from a buffer until a newline is found For practice, I wrote a small program that goes through a string in the data section (although, it could be easily adapted to take user input), and print out the characters in the string until it finds a newline, then stops.
This is by far the most complicated assembly program I've ever written. It's the first time I've ever used a jump and cmp. It's simple, but there's likely improvements I can make, so I thought I'd try to get feedback.
I decided to write it in 32-bit because the system calls are a little easier to wrap my head around. I'll transition to x86-64 once I know what exactly my school is going to be using; because I've seen both so far in slides.
firstjmp.asm
global _start

section .data
    input: db `1234567890\n`

section .text
    _start:
        mov esi, input  ; Current head of string

        .loop:
            mov eax, 4
            mov ebx, 1
            mov ecx, esi
            mov edx, 1
            int 0x80

            inc esi
            
            cmp BYTE [esi], 10
            jne .loop  ; Stop looping once we've found the newline

        mov eax, 1
        mov ebx, 0
        int 0x80


nasm firstjmp.asm -g -f elf32 -Wall -o firstjmp.o
ld firstjmp.o -m elf_i386 -o firstjmp

┌─[brendon@parrot]─[~/Desktop/Classes/CompArc/Lab4/asm]
└──╼ $./firstjmp 
1234567890┌─[brendon@parrot]─[~/Desktop/Classes/CompArc/Lab4/asm]
I haven't used nasm, but superficially, it looks like you are calling out to the kernel for each character in the string.  This is likely to be a relatively expensive operation.
Looking at this, it would appear that edx can be used to specify the number of characters to output.  With this in mind, it would probably be more efficient to find the string length first and then output the entire string in a single system call.
It's also worth considering breaking up your logic into functions.  This doesn't make a lot of difference with such a small program, however it'll be important as you start trying to do more complex logic.  I'm not sure what the standard calling conventions are, however you could end up with something 'like' this...
global _start

section .data
    input: db `1234567890\n`

section .text
    _exit:
        mov eax, 1
        mov ebx, 0
        int 0x80

    ; Input esi points to string
    ; Output edx contains length
    ; Modifies eax
    _linelen:
        mov eax, esi
        .loop:
            inc eax
            
            cmp BYTE [eax], 10
            jne .loop 
        mov edx, eax
        sub edx, esi
        ret       

    ; Input esi points to string
    ;       edx contains string length
    ; Modifies eax, ebx
    _print:
        mov eax, 4
        mov ebx, 1
        int 0x80
        ret

    _start:
        mov esi, input  ; Current head of string

        call _linelen

        mov ecx, esi
        call _print

        call _exit