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
cinboxECX, 0 ;Compara el valor para saber a que subrutina de calculo saltar
je Sumar_e ;Salta por igual a la etiqueta que Suma
cinboxECX, 1 ;Compara el valor para saber a que subrutina de calculo saltar
je Restar_e ;Salta por igual a la etiqueta que Resta
cinboxECX, 2 ;Compara el valor para saber a que subrutina de calculo saltar
je Multiplicar_e ;Salta por igual a la etiqueta que Multiplica
cinboxECX, 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
jinboxNext_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
jinboxNext_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
jinboxNext_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
jinboxNext_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
cinboxEAX, 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:
cinboxEBX, 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
cinboxEBX, 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
jinboxVuelve ;Salta a la etiqueta vuelve
Complemento_bx:
not EBX ;Niega todos los bits del registro
add EBX, 1
jinboxSeguir ;Salta a la etiqueta seguir
Seguir:
mov ESI, 0 ;Inicializa edi con 0 para usarlo como indice
While_:
cinboxESI, 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
jinboxWhile_ ;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
cinboxESI, 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
jinboxWhile_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
jinboxWhile_loop ;Salta al principio del ciclo
end_while: ;Fin del ciclo (*)
mov ESI, 0 ;Inicializa esi con 0 para utilizarlo como contador
cinboxECX, 0 ;Compara la copia del valor original del segundo operando con 0
jl Casos ;Salta por menor a la etiqueta Casos
cinboxEDX, 0 ;Compara la copia del valor original del primer operando con 0
jl Casos_1 ;Salta por menor a la etiqueta casos_1
jinboxFin ;Salta al final de la subrutina MULTIPLICA_E en caso de no saltar por menor
Casos:
inc ESI ;Incrementa el contador esi
cinboxEDX, 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
jinboxComplemento ;Salta a la etiqueta Complemento
Casos_1:
inc ESI ;Incrementa el contador esi
jinboxComplemento ;Salta a la etiqueta Complemento
Complemento:
cinboxESI, 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
jinboxFin ;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
cinboxECX, 0 ;Compara el valor para saber a que subrutina de calculo saltar
je Sumar_f ;Salta por igual a la etiqueta que Suma
cinboxECX, 1 ;Compara el valor para saber a que subrutina de calculo saltar
je Restar_f ;Salta por igual a la etiqueta que Resta
cinboxECX, 2 ;Compara el valor para saber a que subrutina de calculo saltar
je Multiplicar_f ;Salta por igual a la etiqueta que Multiplica
cinboxECX, 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
jinboxnext_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
jinboxnext_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
jinboxnext_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
jinboxnext_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)
0 comentarios:
Publicar un comentario