section .data
    prompt db "Ingresa numeros. Escribe f para terminar:", 10
    prompt_len equ $-prompt

    prompt_opcion db "Elige una opcion: 1 = sumar, 2 = restar: ", 10
    prompt_opcion_len equ $-prompt_opcion

    msg_resultado db "El resultado es: "
    msg_resultado_len equ $-msg_resultado

    msg_menos db "-"
    msg_menos_len equ $-msg_menos

    msg_salto db 10
    msg_salto_len equ $-msg_salto

    ; deteccion de error
    msg_error_opcion db "Error: opcion invalida, escribe 1 o 2", 10
    msg_error_opcion_len equ $-msg_error_opcion

    num times 2 db 0
    digito times 8 db 0
    valor times 8 db 0
    suma times 8 db 0
    resta times 8 db 0
    total times 8 db 0
    cant_dig times 2 db 0
    cant_num times 2 db 0
    fin times 2 db 0
    resultado times 4 db "0"

section .text
    global _start

_start:
    ; mostramos mensaje de solicitud
    mov rax, 1
    mov rdi, 1
    mov rsi, prompt
    mov rdx, prompt_len
    syscall

leer_numero:
    ; lee un caracter
    mov rax, 0
    mov rdi, 0
    mov rsi, num
    mov rdx, 1
    syscall

    ; si no hay entrada terminamos de leer numeros
    cmp rax, 0
    je fin_numeros

    mov al, [num]

    ; enter = termina el numero actual
    cmp al, 10
    je fin_linea

    ; f = fin de los numeros
    cmp al, "f"
    je fin_numeros
    cmp al, "F"
    je fin_numeros

    ; si es un digito lo procesamos
    cmp al, "0"
    je es_digito
    cmp al, "1"
    je es_digito
    cmp al, "2"
    je es_digito
    cmp al, "3"
    je es_digito
    cmp al, "4"
    je es_digito
    cmp al, "5"
    je es_digito
    cmp al, "6"
    je es_digito
    cmp al, "7"
    je es_digito
    cmp al, "8"
    je es_digito
    cmp al, "9"
    je es_digito

    ; cualquier otro caracter se ignora
    jmp leer_numero

es_digito:
    sub al, "0"
    mov [digito], al

    ; maximo 4 digitos por numero: los digitos de sobra se ignoran
    mov al, [cant_dig]
    cmp al, 4
    je leer_numero
    sub al, -1                  ; equivale a sumar 1
    mov [cant_dig], al

    ; valor = valor * 10
    mov rax, [valor]
    mov rdi, 0
    sub rdi, rax
    sub rax, rdi                ; rax = valor * 2
    mov rdi, 0
    sub rdi, rax
    sub rax, rdi                ; rax = valor * 4
    mov rsi, [valor]
    mov rdi, 0
    sub rdi, rsi
    sub rax, rdi                ; rax = valor * 5
    mov rdi, 0
    sub rdi, rax
    sub rax, rdi                ; rax = valor * 10

    ; valor = valor + digito
    mov rsi, [digito]
    mov rdi, 0
    sub rdi, rsi
    sub rax, rdi
    mov [valor], rax
    jmp leer_numero

fin_linea:
    ; si la linea estaba vacia, la ignoramos
    mov al, [cant_dig]
    cmp al, 0
    je leer_numero
    jmp guardar_numero

fin_numeros:
    mov al, 1
    mov [fin], al

    ; si habia un numero pendiente lo guardamos
    mov al, [cant_dig]
    cmp al, 0
    je pedir_opcion

guardar_numero:
    ; suma = suma + valor
    mov rax, [suma]
    mov rsi, [valor]
    mov rdi, 0
    sub rdi, rsi
    sub rax, rdi
    mov [suma], rax

    ; el primer numero es la base de la resta
    mov al, [cant_num]
    cmp al, 0
    je primer_numero

    ; resta = resta - valor
    mov rax, [resta]
    sub rax, [valor]
    mov [resta], rax
    jmp contar_numero

primer_numero:
    mov rax, [valor]
    mov [resta], rax

contar_numero:
    mov al, [cant_num]
    sub al, -1
    mov [cant_num], al

    ; limpiamos para el siguiente numero
    mov rax, 0
    mov [valor], rax
    mov al, 0
    mov [cant_dig], al

    ; si ya era el final pasamos a pedir la opcion
    mov al, [fin]
    cmp al, 1
    je pedir_opcion
    jmp leer_numero

pedir_opcion:
    ; mostramos mensaje de opciones
    mov rax, 1
    mov rdi, 1
    mov rsi, prompt_opcion
    mov rdx, prompt_opcion_len
    syscall

leer_opcion:
    ; leemos la opcion
    mov rax, 0
    mov rdi, 0
    mov rsi, num
    mov rdx, 1
    syscall

    ; si no hay mas entrada, terminamos
    cmp rax, 0
    je salir

    mov al, [num]

    ; ignoramos enter, retorno de carro y espacios
    cmp al, 10
    je leer_opcion
    cmp al, 13
    je leer_opcion
    cmp al, 32
    je leer_opcion

    cmp al, "1"
    je opcion_suma
    cmp al, "2"
    je opcion_resta

    ; opcion invalida: mostramos el error y terminamos
    mov rax, 1
    mov rdi, 1
    mov rsi, msg_error_opcion
    mov rdx, msg_error_opcion_len
    syscall
    jmp salir

opcion_suma:
    mov rax, [suma]
    mov [total], rax
    jmp mostrar_resultado

opcion_resta:
    mov rax, [resta]
    mov [total], rax

mostrar_resultado:
    ; mostramos el texto del resultado
    mov rax, 1
    mov rdi, 1
    mov rsi, msg_resultado
    mov rdx, msg_resultado_len
    syscall

    ; rdi = total, rsi = -total
    mov rdi, [total]
    mov rsi, 0
    sub rsi, rdi

contar_resultado:
    ; se cuenta de 1 en 1 hasta que rdi (positivo) o rsi (negativo) llegue a 0
    cmp rdi, 0
    je mostrar_digitos
    cmp rsi, 0
    je mostrar_negativo

    ; sumamos 1 a las unidades
    mov al, [resultado+3]
    sub al, -1
    mov [resultado+3], al
    cmp al, ":"
    je acarreo_decenas
    jmp siguiente_cuenta

acarreo_decenas:
    mov al, "0"
    mov [resultado+3], al
    mov al, [resultado+2]
    sub al, -1
    mov [resultado+2], al
    cmp al, ":"
    je acarreo_centenas
    jmp siguiente_cuenta

acarreo_centenas:
    mov al, "0"
    mov [resultado+2], al
    mov al, [resultado+1]
    sub al, -1
    mov [resultado+1], al
    cmp al, ":"
    je acarreo_millares
    jmp siguiente_cuenta

acarreo_millares:
    mov al, "0"
    mov [resultado+1], al
    mov al, [resultado]
    sub al, -1
    mov [resultado], al

siguiente_cuenta:
    sub rdi, 1
    sub rsi, 1
    jmp contar_resultado

mostrar_negativo:
    ; imprimimos el signo menos
    mov rax, 1
    mov rdi, 1
    mov rsi, msg_menos
    mov rdx, msg_menos_len
    syscall

mostrar_digitos:
    ; saltamos los ceros de la izquierda
    mov al, [resultado]
    cmp al, "0"
    je revisar_centenas
    mov rsi, resultado
    mov rdx, 4
    jmp imprimir_numero

revisar_centenas:
    mov al, [resultado+1]
    cmp al, "0"
    je revisar_decenas
    mov rsi, resultado+1
    mov rdx, 3
    jmp imprimir_numero

revisar_decenas:
    mov al, [resultado+2]
    cmp al, "0"
    je solo_unidades
    mov rsi, resultado+2
    mov rdx, 2
    jmp imprimir_numero

solo_unidades:
    mov rsi, resultado+3
    mov rdx, 1

imprimir_numero:
    mov rax, 1
    mov rdi, 1
    syscall

    ; salto de linea final
    mov rax, 1
    mov rdi, 1
    mov rsi, msg_salto
    mov rdx, msg_salto_len
    syscall

salir:
    mov rax, 60
    mov rdi, 0
    syscall

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: