Professional Documents
Culture Documents
1 Resumen
Este documento tiene como objetivo mostrar la interaccin entre los distintos softwares que permiten
generar un ejecutable y el Sistema Operativo. Para realizar esto, se utiliza la herramienta GCC [2] y el
sistema operativo Linux/Debian 2.6
2 Proceso de Compilacin
La compilacin de un programa genera cierta cantidad de archivos [1], los que, es su mayora, no son de
importancia para el programador que est enfocado en generar soluciones en lenguajes de alto nivel [3].
Ejemplos de estos archivos intermedios que pasan desapercibidos son los cdigos assembler (.s) y los
cdigo objeto (.o). El proceso completo de compilacin, se muestra en la figura 1.
Cdigo Cdigo Cdigo
Fuente Fuente Fuente
.c .c .c
Ensamblador
Cdigo Cdigo Cdigo
Objetvo Objetvo Objetvo
.o .o .o
Libreras
Linker del
sistema
(enlazador)
Ejecutable
Figura 1
3 Compilador GCC
GCC es el Gnu C Collection [2]. Posee un conjunto de compiladores, entre los que se encuentran C, C++,
Java, entre otros. El comando gcc es un programa que llama a los distintos programas que permiten
generar el ejecutable deseado.
3.1 Proceso de Compilacin
El proceso de compilacin en C consiste en cuatro etapas: Preprocesado, Compilacin, Ensamblado y
Enlazado.
En el preprocesado, el preprocesador (cpp1) examina los archivos fuente en busca de declaraciones que
comiencen por el smbolo #. Cuando son de tipo #include <archivo>, localiza el archivo indicado
y lo aade al programa. Luego busca y sustituye todas las macros (#define). Una vez realizadas todas
las sustituciones, gcc invoca al compilador.
En la compilacin, el compilador (cc1) toma el cdigo generado por el preprocesador y lo convierte en
cdigo en lenguaje ensamblador.
En el ensamblado, el ensamblador (as) toma el cdigo anterior y lo transforma en cdigo objeto.
1
El preprocesador es llamado a travs de la opcin -E de gcc.
Finalmente, en el enlazado, el programa ld(1)2 lo enlaza a todas las libreras necesarias para que el
cdigo objetivo se puede ejecutar en el sistema operativo. En esta etapa, el linker (ld) es llamado a travs
de otro programa de apoyo (wrapper), llamado collect23.
Prepocesador (cpp)
Busca declaraciones (#) .h
#include : incluye archivo
(1) #define: sustituye Macros
Cdigo
gcc
Fuente Cdigo Fuente
Sin declaraciones #
.i
(2)
.c .h
Compilador (cc1)
Cdigo Assembler
.S
(3)
Ensamblador (as)
Cdigo Objeto
.o
(4)
libreras
Linker (collect1) externas y de
sistema
Ejecutable
holaMundo.c
#include <stdio.h>
#include "global.h"
global.h
main(){
printf("Hola Mundo, %d\n", INI);
} #define INI 2013
Figura 3 Figura 4
Para compilar el cdigo fuente mencionado, se utilizar el modo verbose (-v). Una vez finalizado el
proceso, se puede utilizar el ejecutable generado. Los archivos intermedio son eliminados.
$ gcc -v holaMundo.c -o holaMundo
Using built-in specs.
[...]
gcc version 4.9.2 (Debian 4.9.2-10)
COLLECT_GCC_OPTIONS='-v' '-o' 'holamundo' '-mtune=generic' '-march=i586'
/usr/lib/gcc/i586-linux-gnu/4.9/cc1 -quiet -v -imultiarch i386-linux-gnu holamundo.c -quiet -
dumpbase holamundo.c -mtune=generic -march=i586 -auxbase holamundo -version -o /tmp/ccMxaSyP.s
[...]
COLLECT_GCC_OPTIONS='-v' '-o' 'holamundo' '-mtune=generic' '-march=i586'
as -v --32 -o /tmp/cciMVjMx.o /tmp/ccMxaSyP.s
GNU assembler version 2.25 (i586-linux-gnu) using BFD version (GNU Binutils for Debian) 2.25
COMPILER_PATH=/usr/lib/gcc/i586-linux-gnu/4.9/:/usr/lib/gcc/i586-linux-
gnu/4.9/:/usr/lib/gcc/i586-linux-gnu/:/usr/lib/gcc/i586-linux-gnu/4.9/:/usr/lib/gcc/i586-linux-
gnu/
LIBRARY_PATH=/usr/lib/gcc/i586-linux-gnu/4.9/:/usr/lib/gcc/i586-linux-gnu/4.9/../../../i386-
linux-gnu/:/usr/lib/gcc/i586-linux-gnu/4.9/../../../../lib/:/lib/i386-linux-
gnu/:/lib/../lib/:/usr/lib/i386-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/i586-linux-
gnu/4.9/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-o' 'holamundo' '-mtune=generic' '-march=i586'
/usr/lib/gcc/i586-linux-gnu/4.9/collect2 -plugin /usr/lib/gcc/i586-linux-
gnu/4.9/liblto_plugin.so -plugin-opt=/usr/lib/gcc/i586-linux-gnu/4.9/lto-wrapper -plugin-opt=-
fresolution=/tmp/ccgDJsce.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -
plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --
sysroot=/ --build-id --eh-frame-hdr -m elf_i386 --hash-style=gnu -dynamic-linker /lib/ld-
linux.so.2 -o holamundo /usr/lib/gcc/i586-linux-gnu/4.9/../../../i386-linux-gnu/crt1.o
/usr/lib/gcc/i586-linux-gnu/4.9/../../../i386-linux-gnu/crti.o /usr/lib/gcc/i586-linux-
gnu/4.9/crtbegin.o -L/usr/lib/gcc/i586-linux-gnu/4.9 -L/usr/lib/gcc/i586-linux-
gnu/4.9/../../../i386-linux-gnu -L/usr/lib/gcc/i586-linux-gnu/4.9/../../../../lib -L/lib/i386-
linux-gnu -L/lib/../lib -L/usr/lib/i386-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/i586-linux-
2
El linker ld es una herramienta del Sistema Operativo.
3
El programa collect2 es una herramienta provista por gcc.
gnu/4.9/../../.. /tmp/cciMVjMx.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -
lgcc_s --no-as-needed /usr/lib/gcc/i586-linux-gnu/4.9/crtend.o /usr/lib/gcc/i586-linux-
gnu/4.9/../../../i386-linux-gnu/crtn.o/usr/lib/gcc/i486-linux-gnu/4.4.5/crtend.o
/usr/lib/gcc/i486-linux-gnu/4.4.5/../../../../lib/crtn.o
Para visualizar los archivos intermedios, hay que compilar con la opcin save-temps, tal como se
muestra en la figura 6.
% gcc -save-temps -o holaMundo holaMundo.c
% ls -l
total 80
-rw-r--r-- 1 user staff 16 Mar 8 12:44 global.h
-rwxr-xr-x 1 user staff 8756 Mar 8 13:33 holaMundo
-rw-r--r-- 1 user staff 84 Mar 8 12:46 holaMundo.c
-rw-r--r-- 1 user staff 10601 Mar 8 13:33 holaMundo.i
-rw-r--r-- 1 user staff 740 Mar 8 13:33 holaMundo.o
-rw-r--r-- 1 user staff 1271 Mar 8 13:33 holaMundo.s
%
Figura 6
Tal como se menciona en la seccin anterior, revisando las ltimas lneas el archivo holamundo.i
(ver figura 7), se puede observar que es ste archivo el que contiene el cdigo fuente que se compila.
$ tail holaMundo.i
[...]
extern void funlockfile (FILE *__stream) __attribute__
((__nothrow__));
# 916 "/usr/include/stdio.h" 3 4
# 2 "holaMundo.c" 2
# 1 "global.h" 1
# 3 "holaMundo.c" 2
main(){
printf("Hola Mundo, %d\n", 2013);
exit(0);
}
$
Figura 7
As mismo, se puede ver el contenido del archivo holaMundo.s, que contiene el cdigo assembler
del programa. El cdigo assembler se visualiza en la figura 8.
$ more holaMundo.s
.file "holaMundo.c"
.section .rodata
.LC0:
.string "Hola Mundo: %d\n"
.text
.globl main
.type main, @function
main:
.LFB2:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $4, %esp
subl $8, %esp
pushl $2013
pushl $.LC0
call printf
addl $16, %esp
subl $12, %esp
pushl $0
call exit
.LFE2:
.size main, .-main
.ident "GCC: (Debian 4.9.2-10) 4.9.2"
.section .note.GNU-stack,"",@progbits
Debido a que un ejecutable requiere muchas funciones externas del sistema y de libreras de C,
es preferible utilizar el comando gcc:
$ gcc holamundo.o o holamundo.
Observacin:
gcc -E llama internamente al preprocesador cpp.
gcc -S llama internamente al compilador cc1.
Las herramientas cc1 y collect2 se encuentran en el directorio
/usr/lib/gcc/i586-linux-gnu/<version>/ .
_start:
movl $len,%edx # third argument: message length
movl $msg,%ecx # second argument:
# pointer to message to write
movl $1,%ebx # first argument: file handle (stdout)
movl $4,%eax # system call number (sys_write)
int $0x80 # call kernel
msg:
.ascii "Hello, world\n"
len = . - msg
Para crear el ejecutable, se debe ensamblar y ligar de la siguiente manera:
$ as holamundo.s -o holamundo.o
$ ld -s holamundo.o -o holamundo
$ ./holamundo
6 Bibliografa
[1] Operating system concepts, Abraham Silberschatz, Peter Baer Galvin, Greg Gagne, 6 ed.
[2] http://gcc.gnu.org
[3] Estructura y diseo de computadores, David A. Patterson, John L. Hennessy, 2004.
[4] Programacin Avanzada en Unix, Jos Canosa, Mc Graw Hill, 2000.