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
To embed this project on your website, copy the following code and paste it into your website's HTML: