El Alicate
¿Un merengue o un reggaeton? Cuarto y mitad
"Tú lo abres y lo cierras mami"... ¡ma que cosa!
Este tío es el del pescao (es muy mala) que sonó por aquí:
Y sobre todo la de "Mueve Mami":
De todas formas ahí otras muy chulas como la de "si me preguntan donde vivo yo, yo vivo en la discoteca" (que se titula borrachera, un buen merengue).
¿Cómo se compila un programa?
Este artículo es una visión muy ligera.
Tenemos un código que queremos compilar:
~/ejemplo $ cat suma_1y1.c
// Compilame (-S llegar al ensamblador y -o para final):
// gcc -S suma_1y1.c -fdump-tree-all -O0 -Wall
// gcc -o suma_1y1.bin suma_1y1.c -fdump-tree-all -O0 -Wall
#include
int main () {
int i;
int j;
int k;
i = 1;
j = 1;
k = i + j;
printf( "%d + %d = %d\n", i, j, k );
return k;
}
Y luego lo mandamos compilar con unas opciones especiales para ver todos los pasos, sin ninguna optimización y avisándonos de los posibles problemas:
~/ejemplo $ gcc -S suma_1y1.c -fdump-tree-all -O0 -Wall
Y ahora vamos a ver qué ha hecho el compilador. El "suma_1y1.c.001t.tu" es el conjunto de funciones existentes, pero no tiene especial interés.
Veamos el "original":
~/ejemplo $ cat suma_1y1.c.003t.original
;; Function main (main)
;; enabled by -tree-original
{
int i;
int j;
int k;
int i;
int j;
int k;
i = 1;
j = 1;
k = i + j;
printf ((const char * restrict) (char *) "%d + %d = %d\n", i, j, k);
return k;
}
Luego hace el paso a código de tres direcciones:
~/ejemplo $ cat suma_1y1.c.004t.gimple
main ()
{
int D.2026;
int i;
int j;
int k;
i = 1;
j = 1;
k = i + j;
printf (&"%d + %d = %d\n"[0], i, j, k);
D.2026 = k;
return D.2026;
}
Nos saltamos algunos que no son interesantes (vcg, useless, lower, eh, cfg), y llegamos a cplxlower0 en el que vemos que ha detectado un bloque de sentencias (el "segundo"):
~/ejemplo $ cat suma_1y1.c.023t.cplxlower0
;; Function main (main)
main ()
{
int k;
int j;
int i;
int D.2026;
:
i = 1;
j = 1;
k = i + j;
printf (&"%d + %d = %d\n"[0], i, j, k);
D.2026 = k;
return D.2026;
}
Veclower y fixupcfg no tienen mucho interés pero mostraremos la salida de éste último:
~/ejemplo $ cat suma_1y1.c.026t.fixupcfg
;; Function main (main)
main ()
{
int k;
int j;
int i;
int D.2026;
# BLOCK 2
# PRED: ENTRY (fallthru)
i = 1;
j = 1;
k = i + j;
printf (&"%d + %d = %d\n"[0], i, j, k);
D.2026 = k;
return D.2026;
# SUCC: EXIT
}
Tras estos pasos el gcc realiza el siguiente código final para x86:
$ cat suma_1y1.s
.file "suma_1y1.c"
.section .rodata
.LC0:
.string "%d + %d = %d\n"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $36, %esp
movl $1, -16(%ebp)
movl $1, -12(%ebp)
movl -12(%ebp), %eax
addl -16(%ebp), %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
movl %eax, 12(%esp)
movl -12(%ebp), %eax
movl %eax, 8(%esp)
movl -16(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
movl -8(%ebp), %eax
addl $36, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.2.3 (Gentoo 4.2.3 p1.0)"
.section .note.GNU-stack,"",@progbits
Voy a comentar un poco algo del código (comentarios con //)
.file "suma_1y1.c" // fichero que originó este código máquina
.section .rodata
.LC0:
.string "%d + %d = %d\n" // para la llamada a printf
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp // guardamos el marco de pila
movl %esp, %ebp // el nuevo marco pila es la dirección de la pila
pushl %ecx
subl $36, %esp
movl $1, -16(%ebp) // i = 1
movl $1, -12(%ebp) // j = 1
movl -12(%ebp), %eax
addl -16(%ebp), %eax // k = i + j
movl %eax, -8(%ebp)
movl -8(%ebp), %eax // el cuarto parámetro del printf: k
movl %eax, 12(%esp)
movl -12(%ebp), %eax // el tercer parámetro del printf: j
movl %eax, 8(%esp)
movl -16(%ebp), %eax // el segundo parámetro del printf: i
movl %eax, 4(%esp)
movl $.LC0, (%esp) // el primer parámetro del printf: "%d + %d = %d\n"
call printf
movl -8(%ebp), %eax
addl $36, %esp // Se desmonta la pila
popl %ecx
popl %ebp // Se restaura el marco de pila
leal -4(%ecx), %esp // Se restaura el puntero de pila
ret // retorno del main
.size main, .-main
.ident "GCC: (GNU) 4.2.3 (Gentoo 4.2.3 p1.0)"
.section .note.GNU-stack,"",@progbits
Deseas saber más, pues accede a la página del GCC de wikibooks.
Suscribirse a:
Entradas (Atom)