Arquitectura y programación en ensamblador del Intel Pentium

Abelardo Pardo

Universidad Carlos III de Madrid
Departamento de Ingeniería Telemática

Avenida Universidad 30, E28911 Leganés (Madrid), SPAIN


Tabla de contenidos

1. Introducción
1.1. Perspectivas de un ordenador
1.2. Niveles de abstracción
1.2.1. Estudio de un procesador a nivel lenguaje máquina
1.3. Estructura de un ordenador
1.4. Definición de un programa
1.5. El lenguaje ensamblador
1.5.1. Programación en lenguaje ensamblador
1.5.2. Ejecución de un programa en ensamblador
1.6. Ejecución de un programa
1.7. Ejercicios
Bibliografía
2. Codificación de la información
2.1. Lógica binaria
2.1.1. Propiedades de una codificación binaria
2.2. Representación de números en diferentes bases
2.2.1. Traducción de un número a diferentes bases
2.3. Codificación de números naturales
2.4. Codificación en bases 8 y 16
2.5. Tamaño de una codificación
2.6. Codificación de números enteros
2.7. Codificación de números reales
2.7.1. Desbordamiento en la representación en coma flotante
2.7.2. El estándar IEEE 754
2.8. Representación de conjuntos de símbolos
2.8.1. Codificación de caracteres
2.8.2. Codificación de instrucciones
2.8.3. Descripción de un lenguaje máquina
2.9. Ejercicios
Bibliografía
3. Almacenamiento de datos en memoria
3.1. La memoria RAM
3.2. Operaciones sobre memoria
3.3. Conexión entre memoria y procesador
3.4. Almacenamiento de datos
3.4.1. Almacenamiento de booleanos
3.4.2. Almacenamiento de caracteres
3.4.3. Almacenamiento de enteros y naturales
3.4.4. Almacenamiento de instrucciones
3.4.5. Tamaño de datos en operaciones de lectura y escritura
3.5. Almacenamiento de tablas
3.5.1. Almacenamiento de tablas en Java
3.6. Almacenamiento de direcciones de memoria
3.6.1. Ejemplos de indirección
3.7. Ejercicios
4. Arquitectura del Intel Pentium
4.1. El entorno de ejecución del procesador Intel Pentium
4.1.1. Espacio de direcciones
4.1.2. Registros de propósito general
4.1.3. Registro de estado y control
4.1.4. El registro contador de programa
4.1.5. Otros registros del Intel Pentium
4.1.6. Estado visible de un programa
4.2. Ciclo de ejecución de una instrucción
4.2.1. Fase de fetch
4.2.2. Fase de decodificación inicial
4.2.3. Fase de decodificación final
4.2.4. Fase de ejecución
4.2.5. Fase de escritura de resultados
4.2.6. Ejecución de una instrucción
4.2.7. Ciclo de ejecuciones en procesadores actuales
4.3. La pila
4.3.1. Instrucciones de manejo de la pila
4.3.2. El puntero de pila
4.3.3. Valores iniciales del puntero de pila
4.4. Ejercicios
5. Juego de instrucciones
5.1. Tipos de juegos de instrucciones
5.2. Formato de instrucciones máquina del Intel Pentium
5.3. El lenguaje ensamblador
5.3.1. Formato de instrucción ensamblador
5.3.2. Descripción detallada de las instrucciones
5.3.3. Tipos de operandos
5.3.4. El sufijo de tamaño
5.4. Instrucciones más representativas del Intel Pentium
5.4.1. Instrucciones de transferencia de datos
5.4.2. Instrucciones aritméticas
5.4.3. Instrucciones lógicas
5.4.4. Instrucciones de desplazamiento y rotación
5.4.5. Instrucciones de salto
5.4.6. Instrucciones de comparación y comprobación
5.4.7. Instrucciones de llamada y retorno de subrutina
5.5. Ejercicios
6. El programa ensamblador
6.1. Creación de un programa ejecutable en ensamblador
6.2. Definición de datos
6.2.1. Definición de bytes
6.2.2. Definición de enteros
6.2.3. Definición de strings
6.2.4. Definición de espacio en blanco
6.3. Uso de etiquetas
6.4. Gestión de la pila
6.5. Desarrollo de programas en ensamblador
6.6. Ejemplo de programa en ensamblador
6.7. Ejercicios
7. Modos de Direccionamiento
7.1. Notación
7.2. Modos del direccionamiento del Intel Pentium
7.2.1. Modo inmediato
7.2.2. Modo registro
7.2.3. Modo absoluto
7.2.4. Modo registro indirecto
7.2.5. Modo auto-incremento
7.2.6. Modo auto-decremento
7.2.7. Modo base + desplazamiento
7.2.8. Modo base + índice
7.2.9. Modo índice escalado + desplazamiento
7.2.10. Modo base + índice escalado + desplazamiento
7.2.11. Utilización de los modos de direccionamiento
7.3. Hardware para el cálculo de la dirección efectiva
7.4. Resumen de los modos de direccionamiento
7.5. Ejercicios
8. Construcciones de alto nivel
8.1. Desarrollo de aplicaciones en múltiples ficheros
8.2. Programas en múltiples ficheros
8.3. Traducción de construcciones de alto nivel a ensamblador
8.3.1. Traducción de un if/then/else
8.3.2. Traducción de un switch
8.3.3. Traducción de un bucle while
8.3.4. Traducción de un bucle for
8.4. Ejecución de subrutinas
8.4.1. Las instrucciones de llamada y retorno de una subrutina
8.4.2. Paso de parámetros y devolución de resultados
8.5. Gestión del bloque de activación
8.6. Ejemplo de evolución del bloque de activación
8.7. Ejercicios
A. Subconjunto de instrucciones del Intel Pentium
A.1. Nomenclatura
A.2. Instrucciones de movimiento de datos
A.2.1. MOV: Movimiento de datos
A.2.2. PUSH: Instrucción de carga sobre la pila
A.2.3. POP: Instrucción de descarga de la pila
A.2.4. XCHG: Instrucción de intercabmio
A.3. Instrucciones aritméticas
A.3.1. ADD: Instrucción de suma
A.3.2. SUB: Instrucción de resta
A.3.3. INC: Instrucción de incremento
A.3.4. DEC: Instrucción de decremento
A.3.5. NEG: Instrucción de cambio de signo
A.3.6. MUL: Instrucción de multiplicación sin signo
A.3.7. DIV: Instrucción de división sin signo
A.3.8. IMUL: Instrucción de multiplicación con signo
A.3.9. IDIV: Instrucción de división con signo
A.4. Instrucciones lógicas
A.4.1. AND: Instrucción de conjunción
A.4.2. OR: Instrucción de disyunción
A.4.3. XOR: Instrucción de disyunción exclusiva
A.4.4. NOT: Instrucción de negación
A.5. Instrucciones de desplazamiento
A.5.1. SAL/SAR: Desplazamiento aritmético
A.5.2. SHL/SHR: Desplazamiento lógico
A.5.3. RCL/RCR: Instrucción de rotación con acarreo
A.5.4. ROR/ROL: Instrucción de rotación sin acarreo
A.6. Instrucciones de salto
A.6.1. JMP: Instrucción de salto incondicional
A.6.2. Jcc: Instrucciones de salto condicional
A.6.3. CALL: Instrucción de llamada a subrutina
A.6.4. RET: Instrucción de retorno de subrutina
A.7. Instrucciones de comparación y comprobación
A.7.1. CMP: Instrucción de comparación
A.7.2. TEST: Instrucción de comprobación
B. El depurador
B.1. Arranque y parada del depurador
B.2. Visualización de código
B.3. Ejecución controlada de un programa
B.4. Visualización de datos
B.5. Ejercicios
C. Licencia Creative Commons

Lista de figuras

1.1. Perspectiva del programador
1.2. Perspectiva del diseñador
1.3. Diferentes perspectivas de un ordenador
1.4. Relación entre los niveles de abstracción
1.5. Estructura de un ordenador
1.6. Creación de un ejecutable en Java
1.7. Creación de un ejecutable a partir de un programa en lenguaje ensamblador
1.8. Introducción el comando programa
1.9. Copia del ejecutable de disco a memoria
1.10. Ejecución de la primera instrucción de un programa
2.1. Rango de enteros codificados por 8 bits en signo y magnitud
2.2. Rango de enteros codificados por 8 bits en complemento a 2
2.3. Estructura de la representación binaria en coma flotante
2.4. Estructura de las instrucciones de ual-1
2.5. Formato de codificación del conjunto ual-1
2.6. Ejemplo de codificación de instrucción
2.7. Estructura de las instrucciones de ual-2
2.8. Estructura de la correspondencia de ual-2
2.9. Codificación de los operandos en ual-3
2.10. Formato de la codificación de ual-3
3.1. Estructura de la memoria RAM
3.2. Operaciones sobre memoria
3.3. Señales que conectan el procesador y la memoria
3.4. Memoria real y posible en un Intel Pentium
3.5. Almacenamiento de booleanos
3.6. Almacenamiento de un string
3.7. Almacenamiento de enteros en memoria
3.8. Interpretación de bytes en little endian y big endian
3.9. Almacenamiento de instrucciones en formato fijo y variable
3.10. Acceso a memoria en grupos de 4 bytes
3.11. Acceso doble para obtener 4 bytes consecutivos
3.12. Dirección de un elemento de una tabla
3.13. Ejemplo de almacenamiento de una tabla de enteros de 32 bits en memoria
3.14. Almacenamiento de una tabla de seis enteros en Java
3.15. Dirección de memoria almacenada como número natural
3.16. Una posición de memoria “apunta a” otra
3.17. Indirección múltiple para acceder a un dato
3.18. Tabla con direcciones de comienzo de strings
3.19. Dos referencias en Java que apuntan al mismo objeto
3.20. Acceso a un dato mediante doble indirección
3.21. Múltiples Escrituras
4.1. Pentium 4 Northwood (Dic. 2001). Fuente: Intel Technology Journal, vol. 6, núm. 2.
4.2. Chip con un procesador Pentium 4 en su interior
4.3. Tipos de datos del procesador
4.4. Acceso alineado a memoria
4.5. Registros de propósito general
4.6. Registro de estado y control
4.7. Contador de programa
4.8. Ciclos de ejecución de varias instrucciones
4.9. Fase de fetch
4.10. Fase de decodificación inicial
4.11. Fase de decodificación final
4.12. Fase de ejecución
4.13. Fase de escritura de resultado
4.14. Ciclo de ejecución de instrucciones de coma flotante
4.15. Efecto de la instrucción push
4.16. Efecto de la instrucción pop
4.17. Ejecución de instrucciones de pila
4.18. Valores de la cima para la pila vacía y llena
5.1. Formato de Instrucción
5.2. Byte ModR/M de las instrucciones del Intel Pentium
5.3. Byte SIB de las instrucciones de lntel Pentium
5.4. Codificación de una instrucción ensamblador
5.5. Desplazamiento aritmético de 1 bit en un número de 8 bits
5.6. Rotación de un operando de 8 bits
6.1. El programa ensamblador
6.2. Estructura de un programa en ensamblador
6.3. Etiqueta y direcciones relativas a ella
7.1. Dirección de un elemento en una tabla de enteros
7.2. Funcionalidad de los modos de direccionamiento
7.3. Acceso a operando con modo inmediato
7.4. Acceso a operando con modo registro
7.5. Acceso a operando con modo absoluto
7.6. Acceso a operando con modo registro indirecto
7.7. Acceso a operando con modo auto-incremento
7.8. Acceso a operando con modo auto-decremento
7.9. Acceso a operando con modo base + desplazamiento
7.10. Acceso a operando con modo base + índice
7.11. Acceso a operando con modo índice escalado + desplazamiento
7.12. Acceso a operando con modo base + índice escalado + desplazamiento
7.13. Definición de una matriz de enteros almacenada por filas
7.14. Circuito para el cálculo de la dirección efectiva
8.1. Compilación de un programa escrito en un lenguaje de alto nivel
8.2. Referencia a símbolos en dos ficheros
8.3. Reubicación de símbolos en la fase de entrelazado
8.4. Estructura de un if/then/else
8.5. Traducción de un if/then/else a ensamblador
8.6. Estructura de un switch
8.7. Traducción de un switch a ensamblador
8.8. Estructura de un bucle while
8.9. Traducción de un bucle while a ensamblador
8.10. Estructura de un bucle for
8.11. Traducción de un bucle for a ensamblador
8.12. Llamada y retorno de una subrutina
8.13. Invocación anidada de subrutinas
8.14. Parámetros y resultado de una subrutina
8.15. Evolución de la pila desde el punto de vista del programa llamador
8.16. Evolución de la pila durante la llamada a cuenta
B.1. Primer caso en el que realmente se encuentra un bug (Fuente: U.S. Naval Historical Center Photograph)

Lista de tablas

2.1. Potencias de 2
2.2. Conversión de binario a decimal
2.3. Correspondencia entre grupos de 3 bits y dígitos en octal
2.4. Traducción de binario a octal
2.5. Correspondencia entre grupos de 4 bits y dígitos en hexadecimal
2.6. Traducción de binario a hexadecimal
2.7. Ejemplo de codificación de enteros en signo y magnitud
2.8. Representación de números naturales y enteros en binario con n bits
2.9. Parámetros del formato IEEE 754
2.10. Rangos representados en los formatos simple y doble
2.11. Ejemplo de símbolos codificados con Unicode
2.12. Texto de un programa y su codificación en ASCII
2.13. Representación en hexadecimal de símbolos de ual-1
2.14. Codificación del operando lugar
2.15. Representación en binario y hexadecimal de símbolos de ual-2
2.16. Ejemplos de codificación de operandos en ual-3
2.17. Codificación de instrucciones de ual-3
3.1. Unidades de almacenamiento de información en bytes
3.2. Tipos de datos básicos en el lenguaje Java
4.1. Nomenclatura para los tamaños de información
5.1. Instrucciones con diferentes tipos de operandos
5.2. Instrucciones con sufijos de tamaño
5.3. Instrucciones de transferencia de datos
5.4. Instrucciones aritméticas
5.5. Instrucciones de multiplicación
5.6. Instrucciones de división
5.7. Instrucciones lógicas
5.8. Instrucciones de desplazamiento aritmético
5.9. Instrucciones de rotación
5.10. Instrucciones de salto condicional
5.11. Resta y bit de desbordamiento de dos enteros de 2 bits
5.12. Secuencias de instrucciones de comparación y salto condicional
5.13. Secuencias de instrucciones de comprobación y salto condicional
7.1. Modos de direccionamiento del Intel Pentium
8.1. Pasos para la gestión del bloque de activación
A.1. Opciones de la multiplicación sin signo
A.2. Opciones de la división sin signo
A.3. Opciones de la división con signo
B.1. Programa en ensamblador utilizado como ejemplo

Lista de ejemplos

1.1. Programa en Java
1.2. Programa en ensamblador
2.1. Número como suma de potencias de 10
2.2. Multiplicación de números reales por potencias de la base
2.3. Multiplicación por potencias de 2 en números reales binarios
3.1. Almacenamiento de una tabla de strings
3.2. Referencias en el lenguaje Java
3.3. Doble indirección con referencias en el lenguaje Java
5.1. Formato de la instrucción EPSG
5.2. Instrucciones del lenguaje ensamblador
5.3. Descripción de la instrucción de suma de enteros en la arquitectura IA-32
5.4. Uso de saltos condicionales
5.5. Instrucción de comparación antes de salto condicional
6.1. Definición de bytes en ensamblador y sus valores en memoria
6.2. Definiciones de números enteros y sus valores en memoria
6.3. Definición de strings y sus valores en memoria
6.4. Definiciones de espacio en blanco y su valor en memoria
6.5. Definición y manipulación de etiquetas
6.6. Instrucciones para salvar y restaurar registros
6.7. Programa que suma cuatro enteros
7.1. Cálculo de la dirección de un operando mediante instrucciones
7.2. Acceso a los elementos de la pila con el modo registro indirecto
7.3. Acceso a los elementos de una tabla con el modo registro indirecto
7.4. Acceso a una tabla de enteros con modo base + desplazamiento
7.5. Definición y acceso a una tabla de enteros
7.6. Acceso a los enteros de un elemento de una tabla
7.7. Acceso a una tabla de enteros de 64 bits con modo índice escalado + desplazamiento
7.8. Acceso a una tabla de enteros en Java con modo base + índice escalado + desplazamiento
7.9. Instrucciones para incrementar un elemento de una matriz de enteros
7.10. Instrucciones para incrementar un elemento de una matriz de enteros utilizando el modo registro indirecto
8.1. Traducción de un if/then/else a ensamblador
8.2. Traducción de un switch a ensamblador
8.3. Traducción de un bucle while a ensamblador
8.4. Traducción de un bucle for a ensamblador
8.5. Paso de parámetros a través de registros
8.6. Paso de parámetros a través de memoria
8.7. Paso de parámetros a través de la pila
8.8. Definición de variables locales a un método
8.9. Invocación de la rutina cuenta
8.10. Código de la rutina cuenta

Lista de ecuaciones

2.1. Relación entre el número de bits y las posibles combinaciones
2.2. Número mínimo de bits necesarios para codificar N elementos
2.3. Valor de un número de n dígitos en base b
2.4. Obtención de los dígitos en base 7
2.5. Traducción de base 10 a base 2
2.6. Relación entre la cardinalidad del conjunto y el número de bits
5.1. Polinomio de segundo grado para el valor n
7.1. Expresión de la dirección de un dato en memoria
7.2. Dirección efectiva y operando del modo inmediato
7.3. Dirección efectiva y operando del modo registro
7.4. Dirección efectiva y operando del modo absoluto
7.5. Dirección efectiva y operando del modo indirecto
7.6. Dirección efectiva y operando del modo auto-incremento
7.7. Dirección efectiva y operando del modo auto-decremento
7.8. Dirección efectiva y operando del modo base + desplazamiento
7.9. Dirección efectiva y operando del modo base + índice
7.10. Dirección efectiva y operando del modo índice escalado + desplazamiento
7.11. Dirección efectiva y operando del modo base + índice escalado + desplazamiento
7.12. Dirección de un elemento en una matriz de enteros