global _start

section .data
buff times 32 db 0
buffend:
count dq 0

section .text
default rel

_start:
    call read_text
    
    lea rsi, [rel buff]     ; поставить указатель на начало буфера
    call read_num
    call print_num_to_buf
    
    mov rdx, [count]
    call write_text

    mov rax, 60
    mov rdi, 0
    syscall

; Функция складывает два значения
; In: RDI, RSI
; Out: RAX
calculate_sum:
    lea rax, [rdi + rsi]
    ret

; Функция читает текст в буффер
; Регистры не изменяет
read_text:
    push rax
    push rdi
    push rsi
    push rdx

    mov rax, 0          ; sys_read
    mov rdi, 0          ; stdin
    lea rsi, [rel buff]       ; адрес буфера
    mov rdx, 256        ; количество байт
    syscall
    mov [count], rax

    pop rdx
    pop rsi
    pop rdi
    pop rax
    ret

; Функция выводит buff
; In:
;   - RSI - начало буфера
;   - RDX - размер буфера
; Регистры не изменяет
write_text:
    push rax
    push rdi
    push rsi
    push rdx

    mov rax, 1          ; sys_write
    mov rdi, 1          ; stdout
    syscall
    mov [count], rax

    pop rdx
    pop rsi
    pop rdi
    pop rax
    ret


; Функция читает число из stdin
; Out: RAX
read_num:
    push rbx
    push rcx
    xor rbx, rbx        ; обнулить регистр для символов
    xor rax, rax        ; обнулить аккумулирующий регистр
    mov rcx, 10         ; множитель для сдвига

    lea rdi, [rel buff]     ; rdi - конец данных
    add rdi, [count]

    .while:
        cmp rsi, rdi        ; сначала проверяем границы, чтобы не читать за пределами
        jge .return

        mov bl, [rsi]       ; прочитать текущий символ

        cmp bl, 0xA         ; если конец строки (\n) - закончить
        je .return
        cmp bl, 0           ; если null (\0) - закончить
        jz .return
        cmp bl, ' '         ; если пробел - закончить
        jz .return

        mul rcx
        and bl, 0x0F
        add rax, rbx
        inc rsi
        jmp .while

.return:
    pop rcx
    pop rbx
    ret


; Функция выводит число в buff
; In: RAX 
; Out: RSI - указатель на начало строки
print_num_to_buf:
    lea rsi, [buffend]
    dec rsi

    mov rdi, rsi            ; сохранить последний адрес
    mov byte [rsi], 0       ; вписать нуль
    dec rsi
    mov byte [rsi], 0xA     ; вписать перенос строки
    dec rsi
    mov byte [rsi], '0'

    test rax, rax
    jz .return

    .while:
        xor rdx, rdx
        test rax, rax
        jz .break
        mov dl, al
        and dl, 1
        or dl, 0x30
        mov [rsi], dl
        dec rsi
        shr rax, 1
        jmp .while
.break:
    inc rsi
.return:
    sub rdi, rsi
    inc rdi
    mov [count], rdi
    ret
