fbpx

Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

Llamar desde C a fu...
 
Avisos
Vaciar todo

Llamar desde C a funcion en ensamblador

11 Respuestas
2 Usuarios
0 Reactions
95.2 K Visitas
lacabra25
Respuestas: 84
Topic starter
(@lacabra25)
Trusted Member
Registrado: hace 18 años

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.

Responder
10 respuestas
ranganok
Respuestas: 3875
(@ranganok)
Ardero
Registrado: hace 19 años

¿Qué compilador usas?

S2

Ranganok Schahzaman

Responder
lacabra25
Respuestas: 84
Topic starter
(@lacabra25)
Trusted Member
Registrado: hace 18 años

Uso GCC, con el compilo tanto el codigo en C como ensamblo el codigo en ensamblador y linko todos los archivos de codigo objeto.

Responder
ranganok
Respuestas: 3875
(@ranganok)
Ardero
Registrado: hace 19 años

Desempolvando mis apuntes de Ensamblador he encontrado que tienes que hacer lo siguiente (en ensamblador):

nombredelarutina SEGMENT PUBLIC
ASSUME CS:nombredelarutina

_rutina1 PROC FAR
... Aquí el código en ensamblador...
_rutina1 ENDP
PUBLIC _rutina1

_rutina2 PROC FAR
... Aquí el código en ensamblador...
_rutina2 ENDP
PUBLIC _rutina2

... ...

nombre de la rutina ENDS
END

Si accedes a variables globales del fichero C deberán estar declaradas al principio del fichero:
extern _nombrevar:tipovar
donde tipovar es 'byte' 'word' o 'dword'

Esto es lo que tengo, espero que te sirva.

S2

Ranganok Schahzaman

Responder
lacabra25
Respuestas: 84
Topic starter
(@lacabra25)
Trusted Member
Registrado: hace 18 años

Hola, he probado lo que comentas y recivo los siguientes mensages de error al ensamblar:
SNL_funciones_asm.s: Assembler messages:
SNL_funciones_asm.s:5: Error: no such instruction: `encriptar_xornot_asm SEGMENT PUBLIC'
SNL_funciones_asm.s:6: Error: no such instruction: `assume CS:Encriptar_XorNot_Asm'
SNL_funciones_asm.s:7: Error: no such instruction: `_rutina1 PROC FAR'
SNL_funciones_asm.s:62: Error: no such instruction: `_rutina1 ENDP'
SNL_funciones_asm.s:63: Error: no such instruction: `public _rutina1'
SNL_funciones_asm.s:64: Error: no such instruction: `encriptar_xornot_asm ENDS'
SNL_funciones_asm.s:65: Error: no such instruction: `end'

El codigo tras modificarlo me ha quedado asi:
.file "SNL_funciones_asm.s"

.text

Encriptar_XorNot_Asm SEGMENT PUBLIC
ASSUME CS:Encriptar_XorNot_Asm
_rutina1 PROC FAR
# 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 (%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 4(%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
_rutina1 ENDP
PUBLIC _rutina1
Encriptar_XorNot_Asm ENDS
END

No necesito variables globales, prefiero no usar variables globales en C, lo que si necesito es poder acceder a los dos argumentos con que se llama a la funcion desde C en ensamblador.

Responder
Página 1 / 3
Compartir: