epelpad

El post que buscas se encuentra eliminado, pero este también te puede interesar

Calculadora en Assembler

Hola gente, hace mucho que no subo nada y hoy les traigo una CALCULADORA hecha en lenguaje ENSAMBLADOR ó ASSEMBLER !!

IMPORTANTE!!!:
El compilador utilizado para compilar este código es NASM

y linkea con librerias de C con el linkeador GCC

Aclaro esto porque hay varias versiones de compiladores y linkeadores para este lenguaje, no todos tienen las mismas sentecias, por esto es que este código corre únicamente con ese compilador y con ese linkeador!!!


Primero el Código en Ensablador, el cual debe ser copiado y pegado en sus respectivos editores y luego guardado con extención " .asm" :






%include "asm_io.inc"

; Organización del Procesador - Año 2013 - Proyecto Final

segment .text
global calculadora_enteros
global calculadora_flotantes
extern division_entera

;-------------------------------- Subrutina Principal Para Enteros --------------------------------

calculadora_enteros:

push EBP ;Empuja el ebp al stack
mov EBP, ESP ;Pone el ebp apuntando al esp


mov ECX, [EBP+16] ;Mueve a ecx el valor de la operación a realizar para lugar saltar a las correspondientes subrutinas de cálculo
cmp ECX, 0 ;Compara el valor para saber a que subrutina de calculo saltar
je Sumar_e ;Salta por igual a la etiqueta que Suma

cmp ECX, 1 ;Compara el valor para saber a que subrutina de calculo saltar
je Restar_e ;Salta por igual a la etiqueta que Resta

cmp ECX, 2 ;Compara el valor para saber a que subrutina de calculo saltar
je Multiplicar_e ;Salta por igual a la etiqueta que Multiplica

cmp ECX, 3 ;Compara el valor para saber a que subrutina de calculo saltar
je Dividir_e ;Salta por igual a la etiqueta que Divide

Sumar_e:
mov EAX, [EBP+8] ;Mueve a eax el primer operando
add EAX, [EBP+12] ;Le suma a eax el valor del segundo operando
jmp Next_e ;Salta al final de la subrutina CALCULADORA_ENTEROS

Restar_e:
mov EAX, [EBP+8] ;Mueve a eax el primer operando
sub EAX, [EBP+12] ;Le resta a eax el valor del segundo operando
jmp Next_e ;Salta al final de la subrutina CALCULADORA_ENTEROS

Multiplicar_e:
push dword [EBP+12] ;Empuja el primer operando
push dword [EBP+8] ;Empuja el segundo operando
call Multiplica_e ;Llama a la subrutina de NASM que realiza la MULTIPLICACIÓN
add ESP, 8 ;Desapila los parámetros
jmp Next_e ;Salta al final de la subrutina CALCULADORA_ENTEROS

Dividir_e:
push dword [EBP+12] ;Empuja el valor del segundo operando
push dword [EBP+8] ;Empuja el valor del primer operando
call division_entera ;Llamada a subrutina de C que divide enteros
add ESP, 8 ;Desapila los parámetros
jmp Next_e ;Salta al final de la subrutina CALCULADORA_ENTEROS

Next_e:
pop EBP ;Desapila el ebp
ret ;Retorna a la dirección apilada por el llamador

;............................Subrutina que realiza la Multiplicación de Enteros ............................
Multiplica_e:
push EBP ;Empuja el ebp al stack
mov EBP, ESP ;Pone el ebp apuntando al esp

mov dword EAX, [ebp+12] ;Mueve a ax el multiplicador
mov dword EBX, [ebp+8] ;Mueve a bx el multiplicando
mov dword ECX, [ebp+12] ;Mueve a cx el multiplicador
mov dword EDX, [ebp+8] ;Mueve a dx el multiplicando

cmp EAX, 0 ;Compara ax con 0 para saber si es negativo
jl Complemento_ax ;Si es menor que 0 salta a la etiqueta que lo convierte en positivo

Vuelve:
cmp EBX, 0 ;Compara bx con 0 para saber si es negativo
jl Complemento_bx ;Si es menor que 0 salta a la etiqueta que lo convierte en positivo

cmp EBX, 0 ;Compara bx con 0 para saber si es positivo
jge Seguir ;Si es mayot que 0 salta a la etiqueta que continua con la ejecucion del programa
Complemento_ax:
not EAX ;Niega todos los bits del registro
add EAX, 1
jmp Vuelve ;Salta a la etiqueta vuelve
Complemento_bx:
not EBX ;Niega todos los bits del registro
add EBX, 1
jmp Seguir ;Salta a la etiqueta seguir
Seguir:

mov ESI, 0 ;Inicializa edi con 0 para usarlo como indice

While_:
cmp ESI, 16 ;Compara el valor del indice con 16(la cantidad de bits a shiftear)
je end_ ;Salta por igual al final del ciclo
shl EBX, 1 ;Shiftea a la izquierda ebx una posición
inc ESI ;Incrementa el indice
jmp While_ ;Salta al principio del ciclo
end_:

mov ESI, 0 ;Incializa edi con 0 para usarlo como indice

While_loop: ;Comienzo del ciclo (*)
mov EDI, EAX ;Mueva a edi el valor del segundo operando
cmp ESI, 16 ;Compara el indice con la cantidad de cicladas a realizar
je end_while ;Salta por igual al final del ciclo

shr EAX, 1 ;Shiftea a la derecha eax una posición
jc Restaurar ;Salta por Carry a la etiqueta Restaurar

inc ESI ;Incrementa el registro usado como indice para el ciclo
jmp While_loop ;Salta al principio del ciclo

Restaurar:
mov EAX, EDI ;Mueve a ax el valor contenido en edi
add EAX, EBX ;Le suma a el multiplicador el multiplicando
shr EAX, 1 ;Shiftea a la derecha eax una posición
inc ESI ;Incrementa el registro usado como indice para el ciclo
jmp While_loop ;Salta al principio del ciclo
end_while: ;Fin del ciclo (*)

mov ESI, 0 ;Inicializa esi con 0 para utilizarlo como contador

cmp ECX, 0 ;Compara la copia del valor original del segundo operando con 0
jl Casos ;Salta por menor a la etiqueta Casos

cmp EDX, 0 ;Compara la copia del valor original del primer operando con 0
jl Casos_1 ;Salta por menor a la etiqueta casos_1
jmp Fin ;Salta al final de la subrutina MULTIPLICA_E en caso de no saltar por menor
Casos:
inc ESI ;Incrementa el contador esi
cmp EDX, 0 ;Compara el valor del primer operando con 0
jnl Complemento ;Salto por NO menor a la etiqueta Complemento
inc ESI ;Incrementa el contador esi en caso de no haber saltado
jmp Complemento ;Salta a la etiqueta Complemento
Casos_1:
inc ESI ;Incrementa el contador esi
jmp Complemento ;Salta a la etiqueta Complemento
Complemento:
cmp ESI, 1 ;Compara el valor del contador con 1
jne Fin ;Salta por distinto al final de la Subrutina MULTIPLICA_E(no debe modificar los signos)
not EAX ;En caso de no haber saltado niega el valor del resultado
add EAX, 1 ;Le suma 1 al valor negado para completar el Complemento a la Base
jmp Fin ;Salta al final de la Subrutina MULTIPLICA_E

Fin:
pop EBP ;Desapila el ebp
ret ;Retorna a la dirección apilada por el llamador

;--------------------------------- Subrutina Principal Para Flotantes --------------------------------------
calculadora_flotantes:

push EBP ;Empuja el ebp al stack
mov EBP, ESP ;Pone el ebp apuntando al esp

mov ECX, [EBP+16] ;Mueve a ecx el valor de la operación a realizar para lugar saltar a las correspondientes subrutinas de cálculo
cmp ECX, 0 ;Compara el valor para saber a que subrutina de calculo saltar
je Sumar_f ;Salta por igual a la etiqueta que Suma

cmp ECX, 1 ;Compara el valor para saber a que subrutina de calculo saltar
je Restar_f ;Salta por igual a la etiqueta que Resta

cmp ECX, 2 ;Compara el valor para saber a que subrutina de calculo saltar
je Multiplicar_f ;Salta por igual a la etiqueta que Multiplica

cmp ECX, 3 ;Compara el valor para saber a que subrutina de calculo saltar
je Dividir_f ;Salta por igual a la etiqueta que Divide

Sumar_f:
fld dword [EBP+8] ;Pone el primer operando en el tope de la pila de flotantes (ST0)
fadd dword [EBP+12] ;Le suma al tope de la pila el segundo operando
jmp next_f ;Salta al final de la subrutina CALCULADORA_FLOTANTES

Restar_f:
fld dword [EBP+8] ;Pone el primer operando en el tope de la pila de flotantes (ST0)
fsub dword [EBP+12] ;Le resta al tope de la pila el segundo operando
jmp next_f ;Salta al final de la subrutina CALCULADORA_FLOTANTES

Multiplicar_f:
fld dword [EBP+8] ;Pone el primer operando en el tope de la pila de flotantes (ST0)
fmul dword [EBP+12] ;Multiplica el valor del tope de la pila el segundo operando
jmp next_f ;Salta al final de la subrutina CALCULADORA_FLOTANTES

Dividir_f:
fld dword [EBP+8] ;Pone el primer operando en el tope de la pila de flotantes (ST0)
fdiv dword [EBP+12] ;Divide el valor del tope de la pila por el segundo operando
jmp next_f ;Salta al final de la subrutina CALCULADORA_FLOTANTES

next_f:
pop EBP ;Desapila el ebp
ret ;Retorna a la dirección apilada por el llamador

-------------------------------------------------------------------------------------------------------------------------

Por último el código en C " libreria utilizada por el código de Ensamblador" , el cual debe ser copiado, luego pegado en sus respectivos editores y guardado con extensión " .c " :

#include <stdio.h>
#include <stdlib.h>

#define ENTEROS 0
#define FLOTANTES 1

int calculadora_enteros(int op1, int op2, int operacion);
float calculadora_flotantes(float op1, float op2, int operacion);

/*
* Programa principal: computan las operaciones aritméticas entre dos operandos enteros o flotantes.
*/
int main(int argc, char * argv[]){
int operacion;
int tipoOperandos;
char op2[100];
char op1[100];
int res_entero;
float res_flotante;

printf("Ingrese el tipo de los operandos [0->Enteros, 1->Flotantes]: n";
scanf("%d",&tipoOperandos);

//Lectura de operandos por entrada estándar
printf("Ingrese el primer operando: n";
scanf("%s",op1);
printf("Ingrese el segundo operando: n";
scanf("%s",op2);

printf("Ingrese la operación que desea realizar [ 0->suma ,1->resta ,2->multiplicación ,3->división]: n";
scanf("%d",&operacion);


switch(tipoOperandos){

case ENTEROS:{
res_entero = calculadora_enteros(atoi(op1), atoi(op2), operacion);
printf("Resultado = %dn",res_entero);
break;
}
case FLOTANTES:{
res_flotante = calculadora_flotantes(atof(op1), atof(op2), operacion);
printf("Resultado = %fn",res_flotante);
break;
}
default:
printf("Operación no válida.n";
}
}

/*
* Rutina que obtiene el cociente de la división entera entre a y b.
* Esta rutina debe ser invocada desde la rutina calculadora_enteros (programada en assembler),
* cuando el operador es división (3).
*/
int division_entera(int a, int b) {
return a / b;
}


Dejo los comandos para correr este programa desde consola en linux-ubuntu:

nasm -f elf Calculadora.asm ------ Compila el código assembler
gcc -o Calculadora calcular.c Calculadora.o asm_io.o -------- linkea el archivo objeto generado
por el compilador con las librerias
"calcular" y "asm_inc" de C
./Calculadora ------------- Corre el programa por consola


NOTA: Los archivos ".asm" y ".c" deben estar en la misma ruta de destino para poder linkearlos entre ellos!!!


No es agradable a la vista el post, pero creo que es un buen aporte! es un proyecto de la materia Organizacion del Procesador de 2do año de la carrera de Analista en Computacion de la Universidad Nacional de Rio Cuarto, hecho por mi y un compañero!

Recuerden Indentar correctamente, Saludos!!!


El que tenga problemas al copiar las sentencias por los simbolos, etc, si me manda un mensaje privado le envio por email el archivo hecho por mi para no tener que hacer un Copy-Paste desde aqui al editor de texto (ya que normalmente suele generar problemas)

13 comentarios - Calculadora en Assembler

StyleNq +2
te sugiero que la publiques en foros como portalhacker.net o elhacker.com u otros foros de programacion, ahi te pueden dar una mano y ayudarte con sugerencias con el codigo. saludos sigue asi (=
cheatr4
No conocia esos foros! Gracias por la info!
StyleNq
@cheatr4 el segundo tambien era elhacker.net, no hay problema, yo deje un poco de lado la programacion si no con gusto te daria una mano
eduardo7000 +1
Este lenguaje lo leí hace un tiempo y es algo complicado de entender, pero tiene buenos resultados
cheatr4
Tiene metodos muy rebuscados para manejar los datos, pero esta bueno saber manejarlo ! y resulta complicado porque no se asemeja en nada a los lenguajes de alto nivel!
eruca_sativa2 +1
conoces algún buen tutorial para aprender assembler (desde cero)?
cheatr4 +1
Tutorial No, pero si un buen libro!! http://www.etnassoft.com/biblioteca/lenguaje-ensamblador-para-pc/
DbaseIII
poned el código entre las etiquetas [*code] [*/code]
quita los ateriscos
xxxfaaxxx +2
Che no entiendo porque hiciste la calculadora en ASM y la llamas desde C jeje era asi el proyecto? Siempre tan garca los profesores!

@eruca_sativa2 Assembler no se puede aprender facil como un lenguaje. Principalmente porque tenes que ver en que arquitectura se trabaja. Lo mejor es que aprendas a resolver problemas, plantea el algoritmo y despues en cada CPU buscas el set de instrucciones. No es lo mismo un ASM de HC11 que un ASM de un intel I5 jeje

Saludos,
eruca_sativa2 +1
@cheatr4 gracias che!
xxxfaaxxx
@cheatr4 Claro igual hay que ver yo en la facultad cuando di la materia que me enseñaba eso aprendi a usar el HC11, y hoy en dia por ejemplo para el compilador que estoy haciendo (4to año Ing.) las instrucciones no son las mismas pero se el concepto de como trabaja. Igual lo odio a ASM!!
cheatr4
@xxxfaaxxx jajajaj no es un lenguaje muy amigable, pero es estricamente necesario para desburrar a culaquier programador, por ese simple hecho es que lo enseñan en la carrera!
Suipachense +1
Es para agradecer con los lenguajes que podemos trabajor hoy en dia! Aguante la orientación a objetos!
BrayanG26
Como y donde aprendiste ensamblador?
cheatr4
En la universidad y leyendo el libro que esta mencionado mas arriba en los comentarios!
BrayanG26
@cheatr4 mmm
Yo la veerdad no estoy seguro si en mi universidad enseñen eso
me imagino que es cosa de uno mismo
Francokapo_99
capo no tenes una introduccion a asm en general, independientemente del procesador, me perdi un par de clases en la facu y estoy casi en bolas, con el set de instrucciones de un 8086 y un software que se llama winIDE pero no cazo una
cheatr4
no, en los comentarios deje el link de un libro que trabaja con el set de instrucciones para el 80386 y el software que mencionas no lo conozco, usamos NASM en linux para compilar y djgpp para linkear con C, disculpa que no te pueda ayudar!
alexhen
Ni hablar de emsamblador , ahorita estoy con mips32 , es una locura , extraño mucho a c++