Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
highlevel:c:clinux [2010/09/26 20:58] alfred |
highlevel:c:clinux [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 451: | Línea 451: | ||
| ===== Librerías ===== | ===== Librerías ===== | ||
| ==== Estáticas ==== | ==== Estáticas ==== | ||
| + | |||
| ==== Dinámicas ==== | ==== Dinámicas ==== | ||
| + | ===== Otros ===== | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== Insertar código ensamblador ==== | ||
| + | === Ensamblador inline === | ||
| + | gcc permite insertar código ensamblador en medio de código C, este código es denominado ''inline assembly'' y, al ser en Linux, sigue la sitnaxis AT&T. \\ | ||
| + | Para la inserción de código inline utilizaremos la función especial es ''<nowiki>__asm__</nowiki>'', su sintaxis es: | ||
| + | <code> | ||
| + | __asm__ ("instrucciones" : lista_salida : lista_entrada : lista_destruida); | ||
| + | </code> | ||
| + | Las //instrucciones// es un string donde está el código ensamblador. La //lista de salida// son los registros donde se guardará algún dato. La //lista de entrada// son los registros y variables que se utilizaran dentro del código. La //lista destruida// son los registros que han sido modificados por las instrucciones (para que gcc sepa cuales ha de reservar en un futuro). A las variables y registros utilizados en el código se les hace referencia a partir de un índice (que empieza por 0 (indicado con ''%'') y cuenta a partir de la lista de salida y se les une las demás). | ||
| + | <code c> | ||
| + | int i = 100; | ||
| + | __asm__ ("movl %0, %%eax" : : "g" (i)); | ||
| + | </code> | ||
| + | En este caso ''%0'' corresponde al valor de entrada ''i''; el acceso al registro ''eax'' se hace mediante ''<nowiki>%%</nowiki>'' (esto se ha de hacer para cada registro); lo que el código hace es asignar el valor de ''i'' (100) a ''eax''. \\ | ||
| + | La directiva ''"g"(i)'' indica al compilador donde almacenar el parámetro. "r" le permitiría guardar la variable en cualquier registro qeu no esté en uso. "a" en ax\eax, "b" en bx\ebx, "c" en cx\ecx, "d" en dx\edx, "D" en di\edi, "S" en si/esi, etc. | ||
| + | <code c> | ||
| + | void *memcpy( void *dest, const void *src, unsigned int n) | ||
| + | { | ||
| + | __asm__("cld ; rep ; movsb": : "c" ((unsigned int) n), "S" (src), "D" (dest)); | ||
| + | return dest; | ||
| + | } | ||
| + | </code> | ||
| + | También podemos utilizar la directiva ''volatile'' que optimiza el código. | ||
| + | <code c> | ||
| + | int i=0, j=1; | ||
| + | __asm__ __volatile__(" \ | ||
| + | pushl %%eax \n \ | ||
| + | movl %0, %%eax \n \ | ||
| + | addl %1, %%eax \n \ | ||
| + | movl %%eax, %0 \n \ | ||
| + | popl %%eax " | ||
| + | : | ||
| + | : "g" (i), "g" (j) | ||
| + | ); | ||
| + | </code> | ||
| + | Para indicar valores constantes utilizaremos ''$'' delante del valor. \\ | ||
| + | Las variables de salida han de ser precedidas por ''=''. | ||
| + | <code c> | ||
| + | int i=0, j=1, k=0; | ||
| + | __asm__ __volatile__(" \ | ||
| + | pushl %%eax \n \ | ||
| + | movl %1, %%eax \n \ | ||
| + | addl %2, %%eax \n \ | ||
| + | movl %%eax, %0 \n \ | ||
| + | popl %%eax" | ||
| + | : "=g" (k) | ||
| + | : "g" (i), "g" (j) | ||
| + | ); | ||
| + | /* k = i + j; */ | ||
| + | </code> | ||
| + | Si quisieramos decir que después de la llamada al código ensamblador no se toque el ''ecx'' haríamos: | ||
| + | <code c> | ||
| + | __asm__ __volatile__ ("..." : : : "ecx"); | ||
| + | </code> | ||
| + | Podemos insertar etiquetas locales dentro del ensamblador en línea, la llamada a estas debe terminar por una b o una f según si dicha etiqueta esta después o antes de la instrucción de salto: | ||
| + | <code c> | ||
| + | __asm__ __volatile__(" | ||
| + | 0: \n \ | ||
| + | ... | ||
| + | jmp 0b \n \ | ||
| + | ... | ||
| + | jmp 1f \n \ | ||
| + | ... | ||
| + | 1:\n \ | ||
| + | ..." | ||
| + | ); | ||
| + | </code> | ||
| ===== Herramientas ===== | ===== Herramientas ===== | ||
| + | |||
| + | |||
| + | |||
| ==== gcc y g++ ==== | ==== gcc y g++ ==== | ||
| Línea 463: | Línea 545: | ||
| * El parámetro ''-c'' hace que no salga un ejecutable sino uno con código objeto. | * El parámetro ''-c'' hace que no salga un ejecutable sino uno con código objeto. | ||
| * Para realizar el linkage de librerías estáticas (ficheros .lib) en tu proyecto tendrás que utilizar el parámetro ''-l'' seguido del nombre de la librería, pero seguido sin espacios; por ejemplo, tenemos la librería ''ddraw.lib'' o ''gdi32.lib'' haremos ''-lddraw'' o ''-lgdi32''. | * Para realizar el linkage de librerías estáticas (ficheros .lib) en tu proyecto tendrás que utilizar el parámetro ''-l'' seguido del nombre de la librería, pero seguido sin espacios; por ejemplo, tenemos la librería ''ddraw.lib'' o ''gdi32.lib'' haremos ''-lddraw'' o ''-lgdi32''. | ||
| + | * El parámetro ''-I'' agrega un directorio de cabeceras (archivos .h): ''-I/usr/X11R6/include/'' | ||
| + | * El parámetro ''-s'' saca el archivo en ensamblador del compilado. | ||
| * http://iie.fing.edu.uy/~vagonbar/gcc-make/gcc.htm | * http://iie.fing.edu.uy/~vagonbar/gcc-make/gcc.htm | ||
| - | |||
| ==== Debug ==== | ==== Debug ==== | ||