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.
Mostrando entradas con la etiqueta compilador. Mostrar todas las entradas
Mostrando entradas con la etiqueta compilador. Mostrar todas las entradas
¿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.
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.
Etiquetas:
compilación,
compilador,
gcc,
programación
[Friki][Informática][HW] En busca de más instrucciones
Sí, soy yo hablando de HW jajaja. Es cierto, que no me gusta mucho. Parece que se quiere utilizar las GPUs (GPU = tarjeta gráfica) con instrucciones especiales.
Esto significa que desde el microprocesador, podremos lanzar código específico para la tarjeta gráfica.
¿No suena genial?
El problema es que claro el compilador va a tener mucho trabajo o el programador va a tener que saber mucho.
De todas formas, pensandolo un poquito en frío la mayoría de los sistemas están compilados para arquitecturas muy antigüas. Esto nos lleva a pensar ¿Por qué no pueden hacer un estándar y así tener binarios más eficientes?
Por ejemplo, muchas personas se compran el último ordenador y ... un montón de programas que sólo están compilados para arquitecturas de hace años.
¿Qué os parece?
¡Ah! Conocí a un friki que programaba la GPU a pelo para hacer cálculos matemáticos.
Bueno lo vi en /.
Tras toda esta información friki... ¡un video friki!
Etiquetas:
compilador,
friki,
GPU,
HW,
informática
Suscribirse a:
Entradas (Atom)