; Integrantes del equipo:
;   - Nombre Apellido 1
;   - Nombre Apellido 2
;   - Nombre Apellido 3
;
; Programa: Menú para sumar o restar dos números de varios dígitos

section .data
    menu db "===== MENÚ =====", 10, "1. Sumar dos números", 10, "2. Restar dos números", 10, "Elige una opción: "
    menu_len equ $-menu

    prompt_n1 db "Teclea el primer número (máximo 6 dígitos): "
    prompt_n1_len equ $-prompt_n1

    prompt_n2 db "Teclea el segundo número (máximo 6 dígitos): "
    prompt_n2_len equ $-prompt_n2

    mensaje_res db "El resultado es: "
    mensaje_res_len equ $-mensaje_res

    msg_error db "Opción inválida, solo puedes elegir 1 o 2.", 10
    msg_error_len equ $-msg_error

    msg_negativo db "Error: no se permiten números negativos.", 10
    msg_negativo_len equ $-msg_negativo

    msg_no_numero db "Error: solo puedes teclear números del 0 al 9.", 10
    msg_no_numero_len equ $-msg_no_numero

    msg_resta db "Error: en la resta el primer número no puede ser menor que el segundo.", 10
    msg_resta_len equ $-msg_resta

    opcion times 2 db 0
    salto times 2 db 0

    num1 times 8 db 0
    num2 times 8 db 0

    resultado db "0000000000", 10

section .text
    global _start

_start:
    ; Mostramos el menú
    mov rax, 1
    mov rdi, 1
    mov rsi, menu
    mov rdx, menu_len
    syscall

    ; Leemos la opción y después el salto de línea
    mov rax, 0
    mov rdi, 0
    mov rsi, opcion
    mov rdx, 1
    syscall

    mov rax, 0
    mov rdi, 0
    mov rsi, salto
    mov rdx, 1
    syscall

    ; Solo se debe haber tecleado un carácter
    mov bl, [salto]
    cmp bl, 10
    je revisar_opcion
    cmp bl, 0
    je revisar_opcion
    jmp opcion_invalida

revisar_opcion:
    mov al, [opcion]
    cmp al, "1"
    je pedir_numeros
    cmp al, "2"
    je pedir_numeros
    jmp opcion_invalida

pedir_numeros:
    ; rbx guarda en qué variable se lee el número (num1 o num2)
    mov rbx, num1
    mov rsi, prompt_n1
    mov rdx, prompt_n1_len

pedir_numero:
    mov rax, 1
    mov rdi, 1
    syscall

    mov rsi, rbx

leer_numero:
    ; Leemos un carácter a la vez hasta el salto de línea
    mov rax, 0
    mov rdi, 0
    mov rdx, 1
    syscall

    cmp rax, 0          ; ya no hay más que leer
    je fin_lectura

    xor rax, rax
    mov al, [rsi]
    cmp al, 10
    je fin_lectura
    cmp al, "-"
    je numero_negativo

    ; Revisamos que sea un dígito del "0" al "9"
    mov rdx, "0"

revisar_digito:
    cmp rax, rdx
    je digito_valido
    cmp rdx, "9"
    je no_es_numero
    add rdx, 1
    jmp revisar_digito

digito_valido:
    add rsi, 1

    ; Máximo 7 caracteres por número
    mov rdx, rbx
    add rdx, 7
    cmp rsi, rdx
    je fin_lectura
    jmp leer_numero

fin_lectura:
    ; Si no tecleó ningún dígito, no es válido
    cmp rsi, rbx
    je no_es_numero

    ; Si ya leímos el segundo número, pasamos a convertir
    mov rdx, num2
    cmp rbx, rdx
    je convertir

    mov rbx, num2
    mov rsi, prompt_n2
    mov rdx, prompt_n2_len
    jmp pedir_numero

convertir:
    ; Convertimos el primer número de ASCII a número
    mov rsi, num1
    xor rax, rax

convertir_num1:
    xor rbx, rbx
    mov bl, [rsi]
    cmp bl, 10
    je fin_num1
    cmp bl, 0
    je fin_num1

    ; Multiplicamos por 10 usando sumas
    mov rdx, rax
    add rax, rax        ; x2
    add rax, rax        ; x4
    add rax, rdx        ; x5
    add rax, rax        ; x10

    sub bl, "0"
    add rax, rbx
    add rsi, 1
    jmp convertir_num1

fin_num1:
    ; Guardamos el primer número en rdi
    mov rdi, rax

    ; Convertimos el segundo número de ASCII a número
    mov rsi, num2
    xor rax, rax

convertir_num2:
    xor rbx, rbx
    mov bl, [rsi]
    cmp bl, 10
    je fin_num2
    cmp bl, 0
    je fin_num2

    mov rdx, rax
    add rax, rax
    add rax, rax
    add rax, rdx
    add rax, rax

    sub bl, "0"
    add rax, rbx
    add rsi, 1
    jmp convertir_num2

fin_num2:
    ; Revisamos qué opción eligió el usuario
    mov bl, [opcion]
    cmp bl, "1"
    je suma
    cmp bl, "2"
    je resta

suma:
    ; rdi tiene el primer número y rax el segundo
    mov rbx, rdi
    add rbx, rax
    jmp mostrar_resultado

resta:
    mov rbx, rdi

    ; Restamos 1 a ambos hasta que alguno llegue a 0
    ; para saber cuál es mayor
    mov rdx, rbx
    mov rsi, rax

comparar:
    cmp rdx, rsi
    je resta_positiva
    cmp rsi, 0
    je resta_positiva
    cmp rdx, 0
    je resta_invalida
    sub rdx, 1
    sub rsi, 1
    jmp comparar

resta_positiva:
    sub rbx, rax

mostrar_resultado:
    ; El resultado queda en rbx, que no cambia con syscall
    mov rax, 1
    mov rdi, 1
    mov rsi, mensaje_res
    mov rdx, mensaje_res_len
    syscall

convertir_ascii:
    ; Sumamos 1 al último dígito tantas veces como vale rbx
    cmp rbx, 0
    je imprimir_resultado

    mov rsi, resultado
    add rsi, 9

sumar_uno:
    mov al, [rsi]
    add al, 1
    mov [rsi], al
    cmp al, 58          ; 58 es el carácter que sigue después del "9"
    je acarreo

    sub rbx, 1
    jmp convertir_ascii

acarreo:
    ; Si pasó de 9, vuelve a 0 y se suma 1 al dígito de la izquierda
    mov al, "0"
    mov [rsi], al
    sub rsi, 1
    jmp sumar_uno

imprimir_resultado:
    ; Nos saltamos los ceros de la izquierda
    mov rsi, resultado
    mov rdx, resultado
    add rdx, 9

quitar_ceros:
    mov al, [rsi]
    cmp al, "0"
    je revisar_ultimo
    jmp imprimir

revisar_ultimo:
    ; El último dígito se imprime aunque sea 0
    cmp rsi, rdx
    je imprimir
    add rsi, 1
    jmp quitar_ceros

imprimir:
    ; Cantidad de caracteres: dígitos restantes + salto de línea
    mov rdx, resultado
    add rdx, 11
    sub rdx, rsi
    jmp escribir

opcion_invalida:
    mov rsi, msg_error
    mov rdx, msg_error_len
    jmp escribir

numero_negativo:
    mov rsi, msg_negativo
    mov rdx, msg_negativo_len
    jmp escribir

no_es_numero:
    mov rsi, msg_no_numero
    mov rdx, msg_no_numero_len
    jmp escribir

resta_invalida:
    mov rsi, msg_resta
    mov rdx, msg_resta_len

escribir:
    mov rax, 1
    mov rdi, 1
    syscall

    ; Salimos correctamente
    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: