| Ver tema anterior :: Ver siguiente tema | | Autor | Mensaje |
|---|
Pantalàimon_
Registrado: 17 Jul 2007 Mensajes: 90
| Publicado: 27/08/2007 5:35 am | | | Título: librerias estandar |
| Buenas de nuevo.
He estado curioseando por las carpetas de dev-c++, sobretodo mirando a ver que había dentro de las librerías más comunes que uso. Pero me he quedado perplejo al ver que las funciones no están definidas como las definiría en la práctica si yo creara mi propia libreria.
Por poner un ejemplo, en la librería stdio.h hay algun trozo donde van apareciendo los nombres de las funciones delante de la palabra _CRTIMP y despues int __cdecl y con esto se supone que ya esta definida la función?
Bueno, pues quería saber más o menos como funciona todo eso de las librerías estandars para que "funcionen" las funciones.
Saludos! |
| | Volver arriba | |  | cheroky
Registrado: 22 Sep 2005 Mensajes: 1372 Ubicación: En ecx esperando un call
| Publicado: 27/08/2007 5:46 am | | | Título: |
| Hay otros idfentificadores para las funciones como los calling conventions el mecanismo de llamada de las funciones, basicamente implica en que orden se introducen en la pila los argumentos y si esta es limpiada por la funcion llamante, tambien implica si los argumentos se alojaran en rejistros de la cpu, etc, etc.
S2. _________________ - Explícito es mejor que implícito. - Simple es mejor que complejo. - Complejo es mejor que complicado. - Plano es mejor que anidado. - Ralo es mejor que denso. |
| | Volver arriba | |  | Pantalàimon_
Registrado: 17 Jul 2007 Mensajes: 90
| Publicado: 27/08/2007 5:59 am | | | Título: |
| | Ya, ¿pero las funciones de las librerias estan hechas en lenguaje C o en que? |
| | Volver arriba | |  | | mamntc02
Registrado: 30 Abr 2007 Mensajes: 242
| Publicado: 27/08/2007 6:17 am | | | Título: |
| Hola,
Como bien dice cheroky a eso se le llaman 'calling conventions', y le indica al compilador como se pasan los datos de una función a otra (si empezando por la izquierda o por la derecha), y quien vacía esos datos una vez finalizada la función (si la propia función q es llamada o la función q la ha llamado). Todos estos datos van a parar a una zona de memoria, dependiente del proceso, llamada pila.
El lenguaje en el q están hechas las funciones te es igual (aunque será probablemente C, C++ ó assembler), mientras se mantenga la misma convención de llamada. si quieres una buena explicación: http://www.unixwiz.net/techtips/win32-callconv.html ó [url]http://msdn2.microsoft.com/en-us/library/Aa235581(VS.60).aspx[/url] (ambas en inglés)
| Pantalàimon_ escribió: | | Por poner un ejemplo, en la librería stdio.h hay algun trozo donde van apareciendo los nombres de las funciones delante de la palabra _CRTIMP y despues int __cdecl y con esto se supone que ya esta definida la función? |
En stdio.h, al igual q en los otros headers, no se acostumbran a encontrar definiciones (excepto funciones inline) sinó declaraciones. Puede parecer una pedantería, pero creo q es bueno tener los conceptos claros.
Saludos. |
| | Volver arriba | |  | Pantalàimon_
Registrado: 17 Jul 2007 Mensajes: 90
| Publicado: 27/08/2007 7:42 am | | | Título: |
| A ver, el inglés me es bastante chungo y más si es un texto no es para iniciados y empieza a salir vocabulario que ni en castellano se lo que es.
Pero por lo que he entendido, estos comandos __cdecl, etc no definen el cuerpo de la función y lo que hará. Entonces me pregunto dónde estan definidas las funciones, ¿en la pila?, en es caso me pregunto qué es. |
| | Volver arriba | |  | mamntc02
Registrado: 30 Abr 2007 Mensajes: 242
| Publicado: 28/08/2007 12:27 am | | | Título: |
| Hola,
En eso tienes razón, son temas ya más avanzados. Personalmente, creo q no hace falta mucho inglés, ya q la mayoría de vocabulario es técnico, quizá lo q te falte sea parte de ese vocabulario.
Intentaré explicarte un poco por encima como funciona el proceso: Cuando se lanza un proceso o aplicación, el SO el asigna un espacio de direcciones de memoria. Entre dicho espacio se encuentra la memoria estática (q es donde se guardaran los datos estáticos del programa), tienes otra zona llamada heap (en castellano 'montón'), q es de donde obtenemos la memoria reservada dinámicamente (con calloc/malloc ó con new). A parte de esta hay una zona denominada pila (en inglés 'stack'). Si no recuerdo mal tanto la pila como el montón se encuetran en la misma zona de memoria y el montón crece hacia la derecha, mientras la pila hacia la izquierda, es decir:
Imagina q la linea de abajo el espacio de direcciones q nos da el SO, exceptuando la parte estática. Entonces a medida q se necesite memoria dinámicamente (ya sea montón o pila) esta memoria se va gastando. Para q no se interfiera entre el montón y la pila, cada una empieza por un lado del espacio de direcciones, y van creciendo (según necesiten memoria) hacia el lado contrario. |--------------------------------------------------------------------------| |=>Heap Pila<=| (lo siento pero en formato texto esto no se ve bien)
Obviamente se supone q no se deben encontrar, ya q podría dar lugar a un desbordamiento de pila.
Importante: la pila tiene un comportamiento LIFO (el último q llega es el primero en salir)
Llamada a una función:
| Código: | .... mi_resultado = miFuncion(misParametros);
|
Imagina q en un punto del código queremos llamar a miFuncion. Como funciona esto?
Al lanzar un programa, éste se carga en memoria en 'dos partes': datos y código. La parte de datos es aquella q tiene los datos estáticos del programa, en la de código es donde hay el código. Al llamar a una función lo q se hace es decirle al puntero q ejecuta las instrucciones del código q se sitúe en otra posición, y q ejecute lo q hay a partir de ahí. Pero una vez finalizada la ejecución de la función, el programa debe seguir por donde iba, por tanto debe guardar en algún sitio, la posición de memoria siguiente a la llamada de la función para saber donde hay q seguir. Igualmente es posible q la función reciba parámetros o q los devuelva. Toda esta información se pasa por la pila. Por ejemplo, si tu debugases el programa en Assembler, lo q verías sería algo parecido a esto (no es exacto):
| Código: | ... push cs:eip //Almacenamos la posicón de código q estamos ejecutando mov ax, misParametros //Almecenamos nuestros parámetros en variables push ax //Ponemos el valor en la pila call 0x0400000 //Vamos a la dirección del programa donde está el código de la función
|
Ahora en la función verías algo como (imagina q estamos a partir de la posición de memoria 0x0400000)| Código: | pop ax //Recuperamos el parámetro ... //Hacemos lo q hace la función push ax //Almacenamos en la pila el valor q queremos retornar ret //retornamos a la función q nos ha llamado
|
Vamos, por último a lo de las conversiones de llamada. Por ejemplo en el caso __cdecl funciona de la siguiente manera:
- Los parámetros se pasan de derecha a izquierda a la pila, es decir q si tenemos una llamada a una función con dos parámetros, primero se colocará en la pila el de la derecha y luego el de la izquierda:
| Código: | //C++ miFuncion(param1, param2);
//ASM mov ax, param2 push ax mov ax, param1 push ax call @miFuncion
|
Por ser una pila una estructura de datos tipo LIFO, la función recibirá primero el último argumento metido en la pila (param1 en nuestro caso) y así sucesivamente hasta llegar al primero (param2 en nuestro caso) Además se necesita a alguien q, una vez finalizado el proceso de llamada a la función, limpie la pila. En este caso es la misma función invocante, q una vez ha vuelto a recibir el control, le dice a la pila q se mueva hacia la derecha el numero de posiciones necesarias para recuperar el mismo estado q estaba antes de hacer la llamada a la función. Otro tipo de convención de llamada es _stdcall (q es el mismo q WINAPI), el cual también pasa los parámetros de derecha a izquierda, pero es la función q ha sido llamada quien libera la pila, antes de devolver el control a la función q la ha llamado.
Bueno, espero q aún no te hayas suicidado  Sé q todo esto es un poco duro para entenderlo todo a la primera, y yo tampoco es q sea la óstia explicándome . Te recomiendo una web (esta sí q es en castellano), donde yo he aprendido mucho, y no sé pq casi nunca la recomiendo. Tiene un muy buen curso de C++ (y también C), y muy profundo. Quizá en un primer vistazo pueda parecer un poco duro (ya q da muchos detalles técnicos), pero creo q está muy bien. La página general del curso es: http://www.zator.com/Cpp/index.htm, te doy además un par de links más de la misma web, donde se explican los temas de la pila, montón, etc.. y mucho más claros q yo: Organización lógica de Almacenamiento de datos y Organización física
PD: Ah! Y también te recomiendo un poquito (no es necesario mucho) de inglés, q creo q es imprescindible para aprender a programar, pq casi todo está en este idioma, y luego se va traduciendo a otros.
Saludos. |
| | Volver arriba | |  | | mamntc02
Registrado: 30 Abr 2007 Mensajes: 242
| Publicado: 28/08/2007 12:35 am | | | Título: |
| Por cierto, la misma web q te he recomendado antes también tiene explicación de la conversiones de llamada, y es posible q te quede mucho más claro: http://www.zator.com/Cpp/E4_4_6.htm, y dentro de esta sección, el enlace de 'formas de invocación'
Saludos. |
| | Volver arriba | |  | Pantalàimon_
Registrado: 17 Jul 2007 Mensajes: 90
| Publicado: 28/08/2007 5:29 am | | | Título: |
| Gracias por el tiempo tomado, te lo agradezco un montón.
P.D.: que cracks tenemos por estos foros, no?  |
| | Volver arriba | |  | cheroky
Registrado: 22 Sep 2005 Mensajes: 1372 Ubicación: En ecx esperando un call
| Publicado: 28/08/2007 9:00 am | | | Título: |
| Conozco la web de zator desde hace tiempo y ciertamente es de lo mejor ;-)
No siempre se pushea/popea la pila, un compilador decente traducira el codigo a algo similar a: Con puntero de pila ebp antes de llamar a la funcion metera el dato en la pila mediante: (suponiendo que los parametros sean de 4bytes)
| Código: | mov dword ptr [ebp], param1 mov dword ptr [ebp-4], param2 call _miFuncion |
luego se llama a la funcion que los recupera de la pila de forma similar.
Siendo la convencion de llamada __cdecl sera la funcion llamante la encargada de actualizar la pila, en este caso esp queda intacto ahorrando instrucciones.
S2. _________________ - Explícito es mejor que implícito. - Simple es mejor que complejo. - Complejo es mejor que complicado. - Plano es mejor que anidado. - Ralo es mejor que denso. |
| | Volver arriba | |  | | |
| No puede crear mensajes No puede responder temas No puede editar sus mensajes No puede borrar sus mensajes No puede votar en encuestas
|
|
| |