Calculadora en Lenguaje Ensamblador - Linux x86 & NASM

Iniciado por nicoobe, 24 Febrero 2012, 02:46 AM

0 Miembros y 1 Visitante están viendo este tema.

nicoobe

Hola,
Mi nombre es Nicolás y me acabo de registrar en el foro. Estoy haciendo en una calculadora la cual primero le pide al usuario que ingrese dos números y después le pide que indique que operación desea realizar con estos dos números. Mi calculadora suma, resta y multiplica correctamente pero no es capaz de dividir. Al intentar realizar una división recibo el error "Excepción de coma flotante".

A continuación les dejo mi código:

Código (asm) [Seleccionar]

section .data

   ; Mensajes

   msg1      db      10,'-Calculadora-',10,0
   lmsg1      equ      $ - msg1
   
   msg2      db      10,'Numero 1: ',0
   lmsg2      equ      $ - msg2

   msg3      db      'Numero 2: ',0
   lmsg3      equ      $ - msg3

   msg4      db      10,'1. Sumar',10,0
   lmsg4      equ      $ - msg4

   msg5      db      '2. Restar',10,0
   lmsg5      equ      $ - msg5

   msg6      db      '3. Multiplicar',10,0
   lmsg6      equ      $ - msg6

   msg7      db      '4. Dividir',10,0
   lmsg7      equ      $ - msg7

   msg8      db      'Operacion: ',0
   lmsg8      equ      $ - msg8

   msg9      db      10,'Resultado: ',0
   lmsg9      equ      $ - msg9

   msg10      db      10,'Opcion Incorrecta',10,0
   lmsg10      equ      $ - msg10

   nlinea      db      10,10,0
   lnlinea      equ      $ - nlinea

section .bss
   
   ; Espacios reservados para almacenar los valores proporcionados
   ; por el usuario.
   
   opc         resb    2
   num1      resw   2
   num2      resw    2
   result      resw    2

section .text

   global _start

_start:

   ; Imprimimos en pantalla el mensaje 1
   mov eax, 4
   mov ebx, 1
   mov ecx, msg1
   mov edx, lmsg1
   int 80h
   
   ; Imprimimos en pantalla el mensaje 2
   mov eax, 4
   mov ebx, 1
   mov ecx, msg2
   mov edx, lmsg2
   int 80h
   
   ; Obtenemos el valor de numero1
   mov eax, 3
   mov ebx, 0
   mov ecx, num1
   mov edx, 2
   int 80h

   ; Imprimimos en pantalla el mensaje 3
   mov eax, 4
   mov ebx, 1
   mov ecx, msg3
   mov edx, lmsg3
   int 80h
   
   ; Obtenemos el valor de numero2
   mov eax, 3
   mov ebx, 0
   mov ecx, num2
   mov edx, 2
   int 80h

   ; Imprimimos en pantalla el mensaje 4
   mov eax, 4
   mov ebx, 1
   mov ecx, msg4
   mov edx, lmsg4
   int 80h

   ; Imprimimos en pantalla el mensaje 5
   mov eax, 4
   mov ebx, 1
   mov ecx, msg5
   mov edx, lmsg5
   int 80h

   ; Imprimimos en pantalla el mensaje 6
   mov eax, 4
   mov ebx, 1
   mov ecx, msg6
   mov edx, lmsg6
   int 80h

   ; Imprimimos en pantalla el mensaje 7
   mov eax, 4
   mov ebx, 1
   mov ecx, msg7
   mov edx, lmsg7
   int 80h

   ; Imprimimos en pantalla el mensaje 8
   mov eax, 4
   mov ebx, 1
   mov ecx, msg8
   mov edx, lmsg8
   int 80h
   
   ; Obtenemos la opcion deseada por el usuario
   mov ebx,0
   mov ecx,opc
   mov edx,2
   mov eax,3
   int 80h
   
   mov ah, [opc]   ; Movemos la opcion seleccionada al registro ah
   sub ah, '0'      ; Convertimos de ascii a decimal
   
   ; Comparamos el valor ingresado por el usuario para saber que
   ; operacion desea realizar.
   cmp ah, 1
   je sumar
   cmp ah, 2
   je restar
   cmp ah, 3
   je multiplicar
   cmp ah, 4
   je dividir
   
   ; Si el valor ingresado por el usuario no cumple ninguna de las
   ; condiciones anteriores entonces mostramos un mensaje de error y
   ; finalizamos el programa.
   mov eax, 4
   mov ebx, 1
   mov ecx, msg10
   mov edx, lmsg10
   int 80h
   
   jmp salir

sumar:
   ; Guardamos los numeros en los registros eax y ebx
   mov eax, [num1]
   mov ebx, [num2]
   
   ; Conversion de ascii a decimal
   sub eax, '0'
   sub ebx, '0'
   
   ; Suma
   add eax, ebx
   
   ; Conversion de decimal a ascii
   add eax, '0'
   
   ; Movemos el resultado
   mov [result], eax
   
   ; Imprimimos el mensaje 9
   mov eax, 4
   mov ebx, 1
   mov ecx, msg9
   mov edx, lmsg9
   int 80h
   
   ; Imprimimos el resultado
   mov eax, 4
   mov ebx, 1
   mov ecx, result
   mov edx, 1
   int 80h

   ; Finalizamos el programa
   jmp salir

restar:
   ; Guardamos los numeros en los registros eax y ebx
   mov eax, [num1]
   mov ebx, [num2]
   
   ; Conversion de ascii a decimal
   sub eax, '0'
   sub ebx, '0'
   
   ; Resta
   sub eax, ebx

   ; Conversion de decimal a ascii
   add eax, '0'
   
   ; Movemos el resultado
   mov [result], eax
   
   ; Imprimimos el mensaje 9
   mov eax, 4
   mov ebx, 1
   mov ecx, msg9
   mov edx, lmsg9
   int 80h
   
   ; Imprimimos el resultado
   mov eax, 4
   mov ebx, 1
   mov ecx, result
   mov edx, 1
   int 80h

   ; Finalizamos el programa
   jmp salir

multiplicar:
   ; Guardamos los numeros en los registros ax y bx
   mov ax, [num1]
   mov bx, [num2]
   
   ; Conversion de ascii a decimal
   sub ax, '0'
   sub bx, '0'
   
   ; Multiplicacion. AL = AX x BX
   mul bx
   
   ; Conversion decimal a ascii
   add al, '0'
   
   ; Movemos el resultado
   mov [result], al
   
   ; Imprimimos el mensaje 9
   mov eax, 4
   mov ebx, 1
   mov ecx, msg9
   mov edx, lmsg9
   int 80h
   
   ; Imprimimos el resultado
   mov eax, 4
   mov ebx, 1
   mov ecx, result
   mov edx, 1
   int 80h

   ; Finalizamos el programa
   jmp salir
   
dividir:
   ; Guardamos los numeros en los registros ax y bl
   mov ax, [num1]
   mov bl, [num2]

   ; Conversion de ascii a decimal
   sub ax, '0'
   sub bl, '0'
   
   ; Division. AL = AX / BL
   div bl
   
   ; Conversion decimal a ascii
   add al, '0'
   
   ; Movemos el resultado
   mov [result], al
   
   ; Imprimimos el mensaje 9
   mov eax, 4
   mov ebx, 1
   mov ecx, msg9
   mov edx, lmsg9
   int 80h
   
   ; Imprimimos el resultado
   mov eax, 4
   mov ebx, 1
   mov ecx, result
   mov edx, 1
   int 80h
   
   ; Finalizamos el programa
   jmp salir

salir:
   ; Imprimimos dos nuevas lineas
   mov eax, 4
   mov ebx, 1
   mov ecx, nlinea
   mov edx, lnlinea
   int 80h
   ; Finalizamos el programa
   mov eax, 1
   mov ebx, 0
   int 80h


El problema se encuentra dentro de la etiqueta dividir. Es la unica operacion que devuelve un error.

Espero que algun usuario me pueda ayudar a resolver este error.

Muchas Gracias

x64core

podrias poner la linea del error, no tengo nasm talvez con logica se resuelve :P

nicoobe

El error se encuentra en esta parte:
Código (asm) [Seleccionar]


dividir:
   ; Guardamos los numeros en los registros ax y bl
   mov ax, [num1]
   mov bl, [num2]

   ; Conversion de ascii a decimal
   sub ax, '0'
   sub bl, '0'

   ; Division. AL = AX / BL
   div bl

   ; Conversion decimal a ascii
   add al, '0'

   ; Movemos el resultado
   mov [result], al

   ; Imprimimos el mensaje 9
   mov eax, 4
   mov ebx, 1
   mov ecx, msg9
   mov edx, lmsg9
   int 80h

   ; Imprimimos el resultado
   mov eax, 4
   mov ebx, 1
   mov ecx, result
   mov edx, 1
   int 80h

   ; Finalizamos el programa
   jmp salir


Para ser mas exacto esta linea genera el error:

Código (asm) [Seleccionar]

div bl


Al ejecutar esta linea se genera una "Excepción de coma flotante".

x64core

E probado con MASM y me ah funcionado, bueno nose como trabaja la interrupcion 80 o como obtienes los valores
pero estas lineas si num1 y num2 son punteros a los valores estarian bien sino si son los valores en si, entonces esta incorrecto
porque estarias usando los valores como punteros:
  mov ax, [num1]
  mov bl, [num2]


sino, lo mejor es que depures el codigo

nicoobe

Seguí investigando por mi cuenta y modifique la etiqueta dividir.

Ahora quedo así:


dividir:
; Guardamos los numeros en los registros ax y bl
mov dx, 0
mov ax, [num1]
mov bx, [num2]

; Conversion de ascii a decimal
sub ax, '0'
sub bx, '0'
; Division. AX = DX:AX / BX
div bx

; Conversion decimal a ascii
add ax, '0'
; Movemos el resultado
mov [result], ax

; Imprimimos el mensaje 9
mov eax, 4
mov ebx, 1
mov ecx, msg9
mov edx, lmsg9
int 80h

; Imprimimos el resultado
mov eax, 4
mov ebx, 1
mov ecx, result
mov edx, 1
int 80h

; Finalizamos el programa
jmp salir


Sigue sin funcionar pero ya no me genera mas la excepción. El problema ahora es que sin importar que división haga siempre me devuelve 1.

Podra alguien ayudarme? Gracias

nicoobe

Hola a todos,

Quería comentarles que logre finalmente arreglar mi calculadora. A continuación les dejo el código. Espero que le sirva a algún principiante.

Código (asm) [Seleccionar]

section .data

; Mensajes

msg1 db 10,'-Calculadora-',10,0
lmsg1 equ $ - msg1

msg2 db 10,'Numero 1: ',0
lmsg2 equ $ - msg2

msg3 db 'Numero 2: ',0
lmsg3 equ $ - msg3

msg4 db 10,'1. Sumar',10,0
lmsg4 equ $ - msg4

msg5 db '2. Restar',10,0
lmsg5 equ $ - msg5

msg6 db '3. Multiplicar',10,0
lmsg6 equ $ - msg6

msg7 db '4. Dividir',10,0
lmsg7 equ $ - msg7

msg8 db 'Operacion: ',0
lmsg8 equ $ - msg8

msg9 db 10,'Resultado: ',0
lmsg9 equ $ - msg9

msg10 db 10,'Opcion Invalida',10,0
lmsg10 equ $ - msg10

nlinea db 10,10,0
lnlinea equ $ - nlinea

section .bss

; Espacios en la memoria reservados para almacenar los valores introducidos por el usuario y el resultado de la operacion.

opcion: resb 2
num1: resb 2
num2: resb 2
resultado: resb 2

section .text

global _start

_start:

; Imprimimos en pantalla el mensaje 1
mov eax, 4
mov ebx, 1
mov ecx, msg1
mov edx, lmsg1
int 80h

; Imprimimos en pantalla el mensaje 2
mov eax, 4
mov ebx, 1
mov ecx, msg2
mov edx, lmsg2
int 80h

; Obtenemos el numero 1
mov eax, 3
mov ebx, 0
mov ecx, num1
mov edx, 2
int 80h

; Imprimimos en pantalla el mensaje 3
mov eax, 4
mov ebx, 1
mov ecx, msg3
mov edx, lmsg3
int 80h

; Obtenemos el numero 2
mov eax, 3
mov ebx, 0
mov ecx, num2
mov edx, 2
int 80h

; Imprimimos en pantalla el mensaje 4
mov eax, 4
mov ebx, 1
mov ecx, msg4
mov edx, lmsg4
int 80h

; Imprimimos en pantalla el mensaje 5
mov eax, 4
mov ebx, 1
mov ecx, msg5
mov edx, lmsg5
int 80h

; Imprimimos en pantalla el mensaje 6
mov eax, 4
mov ebx, 1
mov ecx, msg6
mov edx, lmsg6
int 80h

; Imprimimos en pantalla el mensaje 7
mov eax, 4
mov ebx, 1
mov ecx, msg7
mov edx, lmsg7
int 80h

; Print on screen the message 8
mov eax, 4
mov ebx, 1
mov ecx, msg8
mov edx, lmsg8
int 80h

; Obtenemos la opcion seleccionada por el usuario
mov ebx, 0
mov ecx, opcion
mov edx, 2
mov eax, 3
int 80h

mov ah, [opcion] ; Movemos la opcion seleccionada a el registro AH
sub ah, '0' ; Convertimos el valor ingresado de ascii a decimal

; Comparamos el valor ingresado por el usuario para saber que operacion realizar.
; JE = Jump if equal = Saltamos si el valor comparado es igual

cmp ah, 1
je sumar

cmp ah, 2
je restar

cmp ah, 3
je multiplicar

cmp ah, 4
je dividir

; Si el valor ingresado no cumple con ninguna de las condiciones anteriores entonces mostramos un mensaje de error y finalizamos
; la ejecucion del programa
mov eax, 4
mov ebx, 1
mov ecx, msg10
mov edx, lmsg10
int 80h

jmp salir

sumar:
; Movemos los numeros ingresados a los registro AL y BL
mov al, [num1]
mov bl, [num2]

; Convertimos los valores ingresados de ascii a decimal
sub al, '0'
sub bl, '0'

; Sumamos el registro AL y BL
add al, bl

; Convertimos el resultado de la suma de decimal a ascii
add al, '0'

; Movemos el resultado a un espacio reservado en la memoria
mov [resultado], al

; Imprimimos en pantalla el mensaje 9
mov eax, 4
mov ebx, 1
mov ecx, msg9
mov edx, lmsg9
int 80h

; Imprimimos en pantalla el resultado
mov eax, 4
mov ebx, 1
mov ecx, resultado
mov edx, 2
int 80h

; Finalizamos el programa
jmp salir

restar:
; Movemos los numeros ingresados a los registro AL y BL
mov al, [num1]
mov bl, [num2]

; Convertimos los valores ingresados de ascii a decimal
sub al, '0'
sub bl, '0'

; Restamos el registro AL y BL
sub al, bl

; Convertimos el resultado de la resta de decimal a ascii
add al, '0'

; Movemos el resultado a un espacio reservado en la memoria
mov [resultado], al

; Imprimimos en pantalla el mensaje 9
mov eax, 4
mov ebx, 1
mov ecx, msg9
mov edx, lmsg9
int 80h

; Imprimimos en pantalla el resultado
mov eax, 4
mov ebx, 1
mov ecx, resultado
mov edx, 1
int 80h

; Finalizamos el programa
jmp salir

multiplicar:

; Movemos los numeros ingresados a los registro AL y BL
mov al, [num1]
mov bl, [num2]

; Convertimos los valores ingresados de ascii a decimal
sub al, '0'
sub bl, '0'

; Multiplicamos. AX = AL X BL
mul bl

; Convertimos el resultado de la resta de decimal a ascii
add ax, '0'

; Movemos el resultado a un espacio reservado en la memoria
mov [resultado], ax

; Imprimimos en pantalla el mensaje 9
mov eax, 4
mov ebx, 1
mov ecx, msg9
mov edx, lmsg9
int 80h

; Imprimimos en pantalla el resultado
mov eax, 4
mov ebx, 1
mov ecx, resultado
mov edx, 1
int 80h

; Finalizamos el programa
jmp salir

dividir:

; Movemos los numeros ingresados a los registro AL y BL
mov al, [num1]
mov bl, [num2]

; Igualamos a cero los registros DX y AH
mov dx, 0
mov ah, 0

; Convertimos los valores ingresados de ascii a decimal
sub al, '0'
sub bl, '0'

; Division. AL = AX / BL. AX = AH:AL
div bl

; Convertimos el resultado de la resta de decimal a ascii
add ax, '0'

; Movemos el resultado a un espacio reservado en la memoria
mov [resultado], ax

; Print on screen the message 9
mov eax, 4
mov ebx, 1
mov ecx, msg9
mov edx, lmsg9
int 80h

; Imprimimos en pantalla el resultado
mov eax, 4
mov ebx, 1
mov ecx, resultado
mov edx, 1
int 80h

; Finalizamos el programa
jmp salir

salir:
; Imprimimos en pantalla dos nuevas lineas
mov eax, 4
mov ebx, 1
mov ecx, nlinea
mov edx, lnlinea
int 80h

; Finalizamos el programa
mov eax, 1
mov ebx, 0
int 80h