Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Hola, he escrito en ensamblador una funcion que antes tenia escrita en C pero que para mejorar la velocidad a la que se ejecute (optimizarla en cuanto a velocidad y memoria necesaria durante su ejecucion) la he escrito en ensamblador y ahora intento llamar desde C a la funcion pero no consigo que funcione todo bien. La funcion en ensamblador la tengo en un archivo .s separado del resto del codigo que lo tengo en C, para la construccion del ejecutable ensamblo por un lado obteniendo un .o y compilo el codigo C por otro obteniendo los .o resultantes y enlazo todo para obtener el ejecutable (todo esto mediante un Makefile, claro). Tras haber estado pasango gdb intentando encontrar el problea no consigo saber nada mas que el problema no parece estar en la llamada a la funcion en ensamblador sino justo al entrar a ejecutar la funcion en ensamblador (dado que aunque tengo experiencia programando en C estoy empezando en ensamblador se me ha ocurrido el haberme equivocado escribiendo el codigo en ensamblador y lo he leido y repasado varias veces pero no consigo encontrar una solucion).
El codigo en C con el que declaro la funcion en ensamblador es el siguiente:extern int Encriptar_XorNot_Asm(char *buffer, char *clave);
La llamada a la funcion escrita en ensamblador es la siguiente:Encriptar_XorNot_Asm(&buffer[0], &clave[0]);
El codigo de la funcion en ensamblador es el siguiente:.file "funciones_asm.s"
.text
.global Encriptar_XorNot_Asm
Encriptar_XorNot_Asm:
# Funcion con la que encriptar una cadena de caracteres
# usando otra como clave haciendo un XOR entre cada byte
# y al resultado aplicandole un NOT. Esta misma funcion
# sirve para desencriptar.
#
# pasamos a EBX el primer argumento, la direccion
# en memoria del primer caracter
MOV 0x04(%ESP),%EBX
# etiqueta con la que crear un segundo bucle con el
# que volver a apuntar al primer caracter de la segunda
# cadena una vez leida completamente para poder continuar
# la encriptacion de la primera cadena de caracteres
B02:
# pasamos a ECX el segundo argumento, la direccion
# en memoria del primer caracter
MOV 0x08(%ESP),%ECX
# etiqueta con la que crear un bucle con el
# que trabajar con las cadenas de caracteres
B01:
# movemos el caracter a realizar el XOR a AL
MOVb (%EBX),%AL
# realizamos un XOR entre AL y el caracter al que
# apunta ECX
XORb (%ECX),%AL
# realizamos un NOT a AL
NOTb %AL
# el resultado obtenido en AL lo pasamos a la
# direccion de memoria apuntada por EBX
MOVb %AL,(%EBX)
# aumentamos los registros EBX y ECX para pasar
# al siguiente caracter
INC %EBX
INC %ECX
# comprobamos si la primera cadena ha sido
# leida completamente
CMP $0x00,(%EBX)
JZ F01
# comprobamos si la segunda cadena ha sido
# leida completamente
CMP $0x00,(%ECX)
JZ B02
# ejecutamos el bucle nuevamente
JMP B01
# etiqueta con la que finalizar la funcion
F01:
# evitamos que se pueda recuperar de los registros
# la direccion en memoria del primer caracter de
# las cadenas de caracteres por seguridad dado
# que esta es una funcion criptografica
MOV $0x00,%EBX
MOV $0x00,%ECX
# retornamos 0
MOV $0x00,%EAX
RET #el valor se retorna en el registro EAX
No he quitado los comentarios de el codigo en ensamblador para facilitar la comprension de que es lo que trataba de hacer en cada paso (independientemente de que lo que en realidad haga pueda ser completamente diferente de lo que pretendia hacer en cada instruccion, espero no haber empezado demasiado mal en ensamblador).
Como no lo he mencionado antes, uso GNU/Linux (trisquel para ser más especifico), GCC y GDB; y trato de que el codigo que escribo sea portable (ya sea por que es portable o por usar compilacion condicionada).
Nota: puse este tema en la seccion de programacion en C por como intento llamar a la funcion desde C, y en la funcion intento obtener todos los argumentos que paso desde C. Si los administradores del foro consideran que estaria mejor en la seccion de ensamblador les agradeceria que lo moviesen.
Hola, si mal no recuerdo (hace mucho que terminé las clases de ensamblador) tienes algunos errores:
_rutina1 debe ser Encriptar_XorNot_Asm
además lo tienes que definir en el makefile.
De todas formas si vas ha hacer una encriptación XOR porqué no usas directamente C ?
void encriptar(unsigned char * msg, unsigned char * clave, int len_msg, int len_clave)
{
int i, j;
j=0;
for(i=0;i< len_msg; i++)
{
msg = !(msg ^ clave[j]);
j++;
if(j> len_clave)
j=0;
}
}
S2
Ranganok Schahzaman
En realidad ya tengo una escrita en C, pero quiero optimizarla en velocidad, quiero tener el maximo control en la velocidad de esa funcion y para ello necesito hacerla en ensamblador para usar el menor numero de instrucciones como sea posible. Aparte de eso, asi aprendo a mezclar el C y el ensamblador.
Sobre los errores, pues seguramente tenga bastantes, estoy empezando con ensamblador y no he encontrado demasiada documentacion en condiciones, que este completa y explique todo en detalle, eso sin tener en cuenta que la mayoria de la documentacion que encuentro no se ha actualizado en unos cuantos años (unos cuantos años largos, no dos o tres).
Lo de definirlo en el makefile es lo que no entiendo, en el makefile indico que lo compile en un archivo objeto (.o) para despues linkar tanto las bibliotecas, el codigo objeto del codigo en C y el codigo objeto del codigo en ensamblador.
Creo recordar que el código ensamblador también lo tenías que compilar primero.
Un Saludo
Ranganok Schahzaman
Tengo entendido que no, un programa en C es preprocesado (aki se sustitullen las macros), es compilado obteniendose un codigo en ensamblador, y por ultimo es ensamblado obteniendose un codigo objeto que para finalizar obteniendo el ejecutable se linkea; un codigo en ensamblador simplemente se ensambla obteniendo el codigo objeto que se linkea para obtener el ejecutable. El codigo es seguro que esta con bastantes errores, estoy aprendiendo ensamblador por lo que es normal, y entre los errores esta que no consigo llamar a la funcion desde C y en ensamblador usar los argumentos pasados, pero el proceso de ensamblado y linkado estoy seguro de ke esta bien, el makefile no creo ke tenga problemas, simplemente lo ensamblo mediante GCC indicandole el archivo del codigo (acabado en .s) y que solo obtenga el codigo objeto, sin linkar, y despues linkeo el codigo objeto del ensamblador junto con el codigo objeto del C, tambien mediante GCC indicandole los archivos objeto.
El lenguaje ensamblador hay que pasarlo a lenguaje máquina (1s y 0s), así que hay que compilarlo igualmente.
S2
Ranganok Schahzaman