Documente Academic
Documente Profesional
Documente Cultură
Departamento de Ingeniería y
Tecnología de Computadores
diciembre de 2010
Índice
Índice
5.1 Introducción
5.1.1 Programas e instrucciones
5.1.2 Codificación de las instrucciones
5.1.3 Tratamiento de las instrucciones
5.1.4 Tipos de instrucciones
5.2 Jerarquía de traducción
5.2.1 Lenguajes de alto nivel
5.2.2 Compiladores y ensambladores
5.2.3 Código objeto
5.2.4 Librerías
5.2.5 Enlazadores y cargadores
5.2.6 Visión global de la jerarquía de traducciones
5.3 Introducción al ISA Intel IA32
5.3.1 Ensamblador del IA32
5.3.2 Operandos de las instrucciones IA32
5.3.3 Repertorio de instrucciones IA32
5.4. Codificación de las instrucciones
5.4.1 Formato y codificación de instrucciones
5.4.2 Ejemplos de codificación en IA32
5.4.3 Reubicación de código
5.4.4 Espacio virtual de direccionamiento
Índice
5.1 Introducción
5.1.1 Programas e instrucciones
5.1.2 Codificación de las instrucciones
5.1.3 Tratamiento de las instrucciones
5.1.4 Tipos de instrucciones
5.2 Jerarquía de traducción
5.2.1 Lenguajes de alto nivel
5.2.2 Compiladores y ensambladores
5.2.3 Código objeto
5.2.4 Librerías
5.2.5 Enlazadores y cargadores
5.2.6 Visión global de la jerarquía de traducciones
5.3 Introducción al ISA Intel IA32
5.3.1 Ensamblador del IA32
5.3.2 Operandos de las instrucciones IA32
5.3.3 Repertorio de instrucciones IA32
5.4. Codificación de las instrucciones
5.4.1 Formato y codificación de instrucciones
5.4.2 Ejemplos de codificación en IA32
5.4.3 Reubicación de código
5.4.4 Espacio virtual de direccionamiento
Programas e instrucciones
Tipos de instrucciones
Índice
5.1 Introducción
5.1.1 Programas e instrucciones
5.1.2 Codificación de las instrucciones
5.1.3 Tratamiento de las instrucciones
5.1.4 Tipos de instrucciones
5.2 Jerarquía de traducción
5.2.1 Lenguajes de alto nivel
5.2.2 Compiladores y ensambladores
5.2.3 Código objeto
5.2.4 Librerías
5.2.5 Enlazadores y cargadores
5.2.6 Visión global de la jerarquía de traducciones
5.3 Introducción al ISA Intel IA32
5.3.1 Ensamblador del IA32
5.3.2 Operandos de las instrucciones IA32
5.3.3 Repertorio de instrucciones IA32
5.4. Codificación de las instrucciones
5.4.1 Formato y codificación de instrucciones
5.4.2 Ejemplos de codificación en IA32
5.4.3 Reubicación de código
5.4.4 Espacio virtual de direccionamiento
#include<stdio.h>
int array[10] = {10,9,8,7,6,5,4,3,2,1};
int i = 0;
int main() {
for(i=0;i<10;i++) /* Recalcula array */
array[i] = array[i]*i;
for(i=0;i<10;i++) /* Imprime array */
printf("%d ",array[i]);
printf("\n");
}
Compiladores y ensambladores
• Compilador:
– Transforma el código en lenguaje de alto nivel (en texto ASCII) a
ensamblador (lenguaje ya “pegado” a la máquina, pero aún
expresado en texto ASCII).
• Ensamblador:
– Convierte el programa ensamblador en un fichero objeto, que ya
contiene datos binarios.
• Contenido de un fichero objeto:
– Instrucciones en lenguaje máquina.
– Datos (ya en formatos de almacenamiento interno: enteros en
C2, reales en punto flotante, texto en ASCII, etc.)
– Información de reubicación (para accesos a memoria, saltos,
etc.) :
• Necesaria porque los programas se dividen en módulos objeto
compilados por separado...
• ...que luego en enlazador (linker) juntará en uno sólo.
• En ese momento, se “pegarán todos los módulos”, se fijarán las
referencias cruzadas entre ellos (acceso a datos o llamadas a
funciones de otro módulo), y se usará la información anterior para
fijar las direcciones definitivas en el programa completo resultante.
Librerías
• Librerías:
– Cuando un programador genera un conjunto de módulos
relacionados, que pueden ser reutilizados por otros...
– ... une todos los ficheros objetos generados en un fichero
llamado librería
• P.e., librerías de cálculo matricial, estadística, programación
de gráficos 3D, de acceso a redes, ...
– Centenares de librerías de funcionalidad muy heterogénea
en una distribución de Linux convencional:
• Para C en concreto, existe una librería estándar (para
entrada/salida en ficheros/pantalla, funciones matemáticas,
etc.), presente en todas las implementaciones
(Windows/Linux/etc.): ejemplo el printf anterior.
– Veremos que el código generado al compilar nuestro
programa acaba enlazándose con código ya precompilado
contenido en ficheros de librería:
• Directorios /lib, /usr/lib, /usr/local/lib y similares, en
Linux.
Librerías
• Librerías estáticas vs. librerías dinámicas:
– Las librerías estáticas almacenan código que, de alguna forma,
es “cortado y pegado” en nuestro ejecutable final.
• Así, si llamamos a más funciones, mayor es el tamaño de nuestro
ejecutable final
• En Linux, están en ficheros con extensión .a
– P.e. /usr/lib/lib*.a, ...
– Las librerías dinámicas, por el contrario, el código de las
funciones de biblioteca no se incluye en el ejecutable final, sino
que éste simplemente almacena la información necesaria para
cargar dicho código en memoria desde el fichero de la librería en
el momento de la ejecución.
• Además, dichas funciones pueden ser compartidas por varios
ejecutables simultáneamente, sin duplicar espacio necesario en
memoria.
• Ventaja principal: no se desperdicia espacio ni en disco ni en
memoria
• Inconveniente principal: el fichero ejecutable, al cambiarlo de
máquina, puede no funcionar (necesita que la(s) librería(s)
utilizada(s) esté(n) en el computador destino)
• En Linux, están en ficheros con extensión .so
– P.e. /usr/lib/lib*.so, ...
Enlazadores y cargadores
• Enlazador (linker):
– Une los distintos objetos generados por el programador
entre sí, ...
– ... y también con las funciones de librería utilizadas,
programadas por otros y preexistentes en el sistema (ya
compiladas y listas para enlazar contra ellas)
• Directorios /lib, /usr/lib, /usr/local/lib/, etc. en Linux
– Genera un fichero ejecutable final
• Cargador (loader):
– Módulo del SO que lee el fichero ejecutable del disco, lo
ubica en memoria y le pasa el control para comenzar la
ejecución.
Índice
5.1 Introducción
5.1.1 Programas e instrucciones
5.1.2 Codificación de las instrucciones
5.1.3 Tratamiento de las instrucciones
5.1.4 Tipos de instrucciones
5.2 Jerarquía de traducción
5.2.1 Lenguajes de alto nivel
5.2.2 Compiladores y ensambladores
5.2.3 Código objeto
5.2.4 Librerías
5.2.5 Enlazadores y cargadores
5.2.6 Visión global de la jerarquía de traducciones
5.3 Introducción al ISA Intel IA32
5.3.1 Ensamblador del IA32
5.3.2 Operandos de las instrucciones IA32
5.3.3 Repertorio de instrucciones IA32
5.4. Codificación de las instrucciones
5.4.1 Formato y codificación de instrucciones
5.4.2 Ejemplos de codificación en IA32
5.4.3 Reubicación de código
5.4.4 Espacio virtual de direccionamiento
#include<stdio.h>
int array[10] = {10,9,8,7,6,5,4,3,2,1};
int i = 0;
int main() {
for(i=0;i<10;i++) /* Recalcula array */
array[i] = array[i]*i;
for(i=0;i<10;i++) /* Imprime array */
printf("%d ",array[i]);
printf("\n");
}
.data .L3: [...Bucle sobre array...] .L6: [... Bucle impresión ...]
[... Segmento datos ...] movl i, %ecx movl i, %eax
array: .long 10 movl i, %eax movl array(,%eax,4),%eax
.long 9 movl array(,%eax,4),%edx movl %eax, 4(%esp)
[...] movl i, %eax movl $.LC0, (%esp)
.long 1 imull %edx, %eax call printf
i: .zero 4 movl %eax, array(,%ecx,4) [...]
.LC0: .string "%d “ movl i, %eax [... codigo finalización ...]
addl $1, %eax ret
.text movl %eax, i [...]
[... Segmento de texto ...] .L2: movl i, %eax
main: [...codigo inicio...] cmpl $9, %eax
jmp .L2 jle .L3
[... Sigue ...] [... Sigue ...]
– Operandos de memoria:
• Muchas instrucciones permiten trabajar directamente con operandos en memoria
(pero no todas)
¡OJO!: distinto de
• Los operandos en memoria pueden expresarse: mov $0x8049628,%ecx
– Con una dirección absoluta: ECX := 0x8049628
– Direccionamiento de memoria
• Carga de una dirección memoria en lugar de un dato
lea 0x4(%esp),%ecx ECX=dirección memoria
(guardada en ESP) +4
– 3. Saltos incondicionales
• Son instrucciones que, cuando el PC llega a ellas y se ejecutan, provocan que
éste cambie a una dirección de código fija, indicada por una etiqueta.
• El programa, por tanto, sigue ejecutándose a partir de la instrucción destino del
salto (en la dirección indicada por la etiqueta correspondiente).
• Rompen la secuencia normal de ejecución del programa (una instrucción tras
otra)
• Por ejemplo: jmp .L1
[...]
.L1: mov %ebx,%eax
• La etiqueta puede estar tanto hacia atrás como hacia delante en el programa:
.L2: mov %ebx,%eax
[...]
jmp .L2
#include<stdio.h>
int array[10] = {10,9,8,7,6,5,4,3,2,1};
int i = 0;
int main() {
for(i=0;i<10;i++)
array[i] = funcion(i);
for(i=0;i<10;i++)
printf("%d ",array[i]);
printf("\n");
}
int funcion(int parametro) {
return array[parametro]*parametro;
}
#include<stdio.h>
int array[10] = {10,9,8,7,6,5,4,3,2,1};
int i = 0;
int main() {
1
for(i=0;i<10;i++)
array[i] = funcion(i); 2
for(i=0;i<10;i++)
printf("%d ",array[i]);
printf("\n");
4 }
int funcion(int parametro) {
return array[parametro]*parametro;
} 3
Índice
5.1 Introducción
5.1.1 Programas e instrucciones
5.1.2 Codificación de las instrucciones
5.1.3 Tratamiento de las instrucciones
5.1.4 Tipos de instrucciones
5.2 Jerarquía de traducción
5.2.1 Lenguajes de alto nivel
5.2.2 Compiladores y ensambladores
5.2.3 Código objeto
5.2.4 Librerías
5.2.5 Enlazadores y cargadores
5.2.6 Visión global de la jerarquía de traducciones
5.3 Introducción al ISA Intel IA32
5.3.1 Ensamblador del IA32
5.3.2 Operandos de las instrucciones IA32
5.3.3 Repertorio de instrucciones IA32
5.4. Codificación de las instrucciones
5.4.1 Formato y codificación de instrucciones
5.4.2 Ejemplos de codificación en IA32
5.4.3 Reubicación de código
5.4.4 Espacio virtual de direccionamiento
Reubicación de código
• Programa cargado en memoria:
– Ya enlazados los objetos y las librerías, en el programa cargado en memoria ya no hay
referencias sin resolver:
Cargado en memoria
Códigos objeto (sin reubicar) (desensamblado y reubicado)
<main>: <main>:
0: 8d 4c 24 04 lea 0x4(%esp),%ecx 0x080483a4: lea 0x4(%esp),%ecx
4: 83 e4 f0 and $0xf0,%esp 0x080483a8: and $0xf0,%esp
[...] [...]
11: c7 05 00 00 00 00 00 movl $0x0,0x0 0x080483b5: movl $0x0,0x804966c
[...] [...]
28: 8b 14 85 00 00 00 00 mov 0x0(,%eax,4),%edx 0x080483cc: mov 0x8049640(,%eax,4),%edx
[...] [...]