/
Inicio :: Foros

 F.A.Q.F.A.Q.                  Conéctese para revisar sus mensajesConéctese para revisar sus mensajes   

librerias estandar

 
      Índice del Foro elrincondelc.com -> Principiantes C/C++
Ver tema anterior :: Ver siguiente tema  
AutorMensaje
Pantalàimon_



Registrado: 17 Jul 2007
Mensajes: 90

MensajePublicado: 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

MensajePublicado: 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

MensajePublicado: 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

MensajePublicado: 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

MensajePublicado: 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

MensajePublicado: 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 Wink
    Sé q todo esto es un poco duro para entenderlo todo a la primera, y yo tampoco es q sea la óstia explicándome Wink. 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

    MensajePublicado: 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

    MensajePublicado: 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? Smile
    Volver arriba
    cheroky



    Registrado: 22 Sep 2005
    Mensajes: 1372
    Ubicación: En ecx esperando un call

    MensajePublicado: 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
          Índice del Foro elrincondelc.com -> Principiantes C/C++
    Página 1 de 1Todas las horas están en GMT - 8 Horas

     
    No puede crear mensajes
    No puede responder temas
    No puede editar sus mensajes
    No puede borrar sus mensajes
    No puede votar en encuestas

    (c) ElRincondelC.com

    Un proyecto de UrlanHeat.com