section .bss
    buffer1 resb 64
    buffer2 resb 64
    out_buf resb 64

section .data
    msg1 db "Enter first number: "
    msg1_len equ $ - msg1

    msg2 db "Enter second number: "
    msg2_len equ $ - msg2

    msg_res db "Sum: "
    msg_res_len equ $ - msg_res

    newline db 10

section .text
    global _start

_start:
    ; --- 1. Read First Number ---
    mov rax, 4                  ; FreeBSD sys_write
    mov rdi, 1
    mov rsi, msg1
    mov rdx, msg1_len
    syscall

    mov rax, 3                  ; FreeBSD sys_read
    mov rdi, 0
    mov rsi, buffer1
    mov rdx, 64
    syscall

    ; --- 2. Read Second Number ---
    mov rax, 4                  ; sys_write
    mov rdi, 1
    mov rsi, msg2
    mov rdx, msg2_len
    syscall

    mov rax, 3                  ; sys_read
    mov rdi, 0
    mov rsi, buffer2
    mov rdx, 64
    syscall

    ; --- 3. Convert Inputs to Integers ---
    mov rsi, buffer1
    call string_to_int
    mov r12, rax                ; Save first number in r12 (preserved across syscalls)

    mov rsi, buffer2
    call string_to_int
    add r12, rax                ; r12 = r12 + second number

    ; --- 4. Print Result Label ("Sum: ") ---
    mov rax, 4                  ; sys_write
    mov rdi, 1
    mov rsi, msg_res
    mov rdx, msg_res_len
    syscall                     ; Kernel runs here; r12 remains perfectly safe!

    ; --- 5. Convert Sum to ASCII String ---
    mov rax, r12                ; Load sum from r12
    mov rdi, out_buf
    call int_to_string          ; Returns string pointer in rsi, length in rdx

    ; --- 6. Print Sum String ---
    mov rax, 4                  ; sys_write
    mov rdi, 1
    ; rsi and rdx are set by int_to_string
    syscall

    ; --- 7. Print Newline ---
    mov rax, 4                  ; sys_write
    mov rdi, 1
    mov rsi, newline
    mov rdx, 1
    syscall

    ; --- 8. sys_exit(0) ---
    mov rax, 1                  ; FreeBSD sys_exit
    mov rdi, 0
    syscall


; =============================================================
; Helper: string_to_int
; =============================================================
string_to_int:
    xor rax, rax
.next_digit:
    movzx rcx, byte [rsi]
    cmp cl, 10                  ; Newline
    je .done
    cmp cl, 13                  ; Carriage return (CRLF support)
    je .done
    cmp cl, 0                   ; Null byte
    je .done
    cmp cl, '0'
    jl .done
    cmp cl, '9'
    jg .done

    sub cl, '0'
    imul rax, 10
    add rax, rcx
    inc rsi
    jmp .next_digit
.done:
    ret


; =============================================================
; Helper: int_to_string
; =============================================================
int_to_string:
    mov rbx, 10
    mov rsi, rdi
    add rsi, 63                 ; Start at end of buffer
    mov byte [rsi], 0           ; Null-terminate
    mov rcx, 0                  ; Length counter

    cmp rax, 0
    jne .convert_loop
    dec rsi
    mov byte [rsi], '0'
    mov rdx, 1
    ret

.convert_loop:
    cmp rax, 0
    je .done_convert
    xor rdx, rdx                ; Clear high bits for 64-bit div
    div rbx                     ; rax = rax / 10, rdx = remainder
    add dl, '0'
    dec rsi
    mov [rsi], dl
    inc rcx
    jmp .convert_loop

.done_convert:
    mov rdx, rcx                ; Return length in rdx
    ret
