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:48] 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 ===== | ||
| - | ===== Herramientas ===== | ||
| - | ===== Notas ===== | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== 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 ===== | ||
| Línea 469: | 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 ==== | ||
| - | Si | + | Si compilamos un código con el parámetro ''-g'' podremos ejecutar el comand ''gdb <archivo salida>'' y nos aparecerá una consola de debugación, los comandos que pueden sernos útiles son: |
| + | * **run** para iniciar el programa. | ||
| + | * **b file:line**, o ''break file:line'', para poner un breakpoint en una línea del programa. | ||
| + | * **delete**, elimina todos los breakpoints. | ||
| + | * **kill** para detener la ejecución del programa. | ||
| + | * **c** o **continue** para continuar la ejecución de un programa parado. | ||
| + | * **quit** para salir de gdb. | ||
| + | * **n** ejecuta la siguiente instrucción. | ||
| + | * **s** ejecuta la siguiente instrucción entrando en funciones. | ||
| + | * **print variable** muestra el valor de la variable indicada. | ||
| + | * **list** muestra las líneas que rodean la actual. | ||
| + | * **info r** muestra los valores de los registros. | ||
| + | * **info stack** muestra la pila. | ||
| + | * **info line** muestra información sobre la línea actual. | ||
| + | * **info locals** muestra las variables locales. | ||
| + | * **source <fichero>** ejecuta un script de gdb. | ||
| + | * **add-symbol-file <fichero>** agrega otro fichero al debug. | ||
| + | |||
| + | ===== Notas ===== | ||
| ==== Links ==== | ==== Links ==== | ||
| * [[https://computing.llnl.gov/tutorials/pthreads|Tutorial de POSIX threads]] | * [[https://computing.llnl.gov/tutorials/pthreads|Tutorial de POSIX threads]] | ||
| + | |||
| ==== Documentos ==== | ==== Documentos ==== | ||
| * {{highlevel:c:programaciongnulinux.pdf|Programación en GNU Linux}} | * {{highlevel:c:programaciongnulinux.pdf|Programación en GNU Linux}} | ||
| * {{highlevel:c:gnu_c_library.pdf|Documentación de la librería GNU C}} | * {{highlevel:c:gnu_c_library.pdf|Documentación de la librería GNU C}} | ||
| + | * {{highlevel:c:gdb-refcard-a4.pdf|Comandos del gdb}} | ||