Programación en ensamblador de la arquitectura IA-32...

198
Programación en ensamblador de la arquitectura IA-32 1 / 198 Programación en ensamblador de la arquitectura IA-32 Universidad Carlos III de Madrid

Transcript of Programación en ensamblador de la arquitectura IA-32...

Page 1: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32 1 / 198

Programación en ensamblador de la arquitectura IA-32

Universidad Carlos III de Madrid

Page 2: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

2 / 198

Copyright © 2007 Universidad Carlos III de Madrid

Page 3: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

3 / 198

COLABORADORES

TÍTULO : REFERENCE :

Programación en ensamblador de la arquitec-tura IA-32

ACCIÓN NOMBRE FECHA FIRMA

ESCRITO POR Abelardo Pardo 6 de mayo de 2008

HISTORIAL DE REVISIONES

NÚMERO FECHA MODIFICACIONES NOMBRE

Page 4: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

4 / 198

Índice general

1. Ejecución de programas en un ordenador 15

1.1. Perspectivas de un ordenador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

1.2. Niveles de abstracción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.2.1. Estudio de un procesador a nivel lenguaje máquina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.3. Estructura de un ordenador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

1.4. Definición de un programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

1.5. El lenguaje ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

1.5.1. Programación en lenguaje ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

1.5.2. Ejecución de un programa en ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

1.6. Ejecución de un programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

1.7. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

1.8. Bibliografía . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

2. Codificación de la información 29

2.1. Lógica binaria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

2.1.1. Propiedades de una codificación binaria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

2.2. Representación de números en diferentes bases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

2.2.1. Traducción de un número a diferentes bases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

2.3. Codificación de números naturales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

2.4. Codificación en bases 8 y 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

2.5. Tamaño de una codificación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

2.6. Codificación de números enteros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

2.7. Codificación de números reales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

2.7.1. Desbordamiento en la representación en coma flotante . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

2.7.2. El estándar IEEE 754 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

2.8. Representación de conjuntos de símbolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

2.8.1. Codificación de caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

2.8.2. Codificación de instrucciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

2.8.3. Descripción de un lenguaje máquina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

2.9. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

2.10. Bibliografía . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

Page 5: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

5 / 198

3. Almacenamiento de datos en memoria 51

3.1. La memoria RAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

3.2. Operaciones sobre memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

3.3. Conexión entre memoria y procesador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

3.4. Almacenamiento de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

3.4.1. Almacenamiento de booleanos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

3.4.2. Almacenamiento de caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

3.4.3. Almacenamiento de enteros y naturales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

3.4.4. Almacenamiento de instrucciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

3.4.5. Tamaño de datos en operaciones de lectura y escritura . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

3.5. Almacenamiento de tablas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

3.5.1. Almacenamiento de tablas en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

3.6. Almacenamiento de direcciones de memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

3.6.1. Ejemplos de indirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

3.7. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

4. Arquitectura IA-32 72

4.1. El entorno de ejecución de la arquitectura IA-32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

4.1.1. Espacio de direcciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

4.1.2. Registros de propósito general . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

4.1.3. Registro de estado y control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

4.1.4. El registro contador de programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

4.1.5. Otros registros de la arquitectura IA-32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

4.1.6. Estado visible de un programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

4.2. Ciclo de ejecución de una instrucción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

4.2.1. Fase de fetch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

4.2.2. Fase de decodificación inicial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

4.2.3. Fase de decodificación final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

4.2.4. Fase de ejecución . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

4.2.5. Fase de escritura de resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

4.2.6. Ejecución de una instrucción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

4.2.7. Ciclo de ejecuciones en procesadores actuales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

4.3. La pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

4.3.1. Instrucciones de manejo de la pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

4.3.2. El puntero de pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

4.3.3. Valores iniciales del puntero de pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

4.4. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

Page 6: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

6 / 198

5. Juego de instrucciones 89

5.1. Tipos de juegos de instrucciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89

5.2. Formato de instrucciones máquina de la arquitectura IA-32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

5.3. El lenguaje ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

5.3.1. Formato de instrucción ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93

5.3.2. Descripción detallada de las instrucciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94

5.3.3. Tipos de operandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

5.3.4. El sufijo de tamaño . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95

5.4. Instrucciones más representativas de la arquitectura IA-32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

5.4.1. Instrucciones de transferencia de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

5.4.2. Instrucciones aritméticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

5.4.2.1. Instrucciones de suma y resta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

5.4.2.2. Instrucciones de multiplicación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

5.4.2.3. Instrucciones de división entera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

5.4.3. Instrucciones lógicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

5.4.4. Instrucciones de desplazamiento y rotación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

5.4.4.1. Instrucciones de desplazamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

5.4.4.2. Instrucciones de rotación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

5.4.5. Instrucciones de salto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

5.4.6. Instrucciones de comparación y comprobación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

5.4.7. Instrucciones de llamada y retorno de subrutina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

5.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

6. El programa ensamblador 109

6.1. Creación de un programa ejecutable en ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

6.2. Definición de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

6.2.1. Definición de bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

6.2.2. Definición de enteros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

6.2.3. Definición de strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

6.2.4. Definición de espacio en blanco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

6.3. Uso de etiquetas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

6.4. Gestión de la pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115

6.5. Desarrollo de programas en ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

6.6. Ejemplo de programa en ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

6.7. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

Page 7: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

7 / 198

7. Modos de Direccionamiento 120

7.1. Notación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

7.2. Modos del direccionamiento de la arquitectura IA-32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

7.2.1. Modo inmediato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

7.2.2. Modo registro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

7.2.3. Modo absoluto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

7.2.4. Modo registro indirecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

7.2.5. Modo auto-incremento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127

7.2.6. Modo auto-decremento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

7.2.7. Modo base + desplazamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

7.2.8. Modo base + índice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

7.2.9. Modo índice escalado + desplazamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133

7.2.10. Modo base + índice escalado + desplazamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

7.2.11. Utilización de los modos de direccionamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

7.3. Hardware para el cálculo de la dirección efectiva . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

7.4. Resumen de los modos de direccionamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

7.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

8. Construcciones de alto nivel 141

8.1. Desarrollo de aplicaciones en múltiples ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

8.2. Programas en múltiples ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

8.3. Traducción de construcciones de alto nivel a ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

8.3.1. Traducción de un if/then/else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

8.3.2. Traducción de un switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

8.3.3. Traducción de un bucle while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

8.3.4. Traducción de un bucle for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

8.4. Ejecución de subrutinas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151

8.4.1. Las instrucciones de llamada y retorno de una subrutina . . . . . . . . . . . . . . . . . . . . . . . . . . 152

8.4.2. Paso de parámetros y devolución de resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

8.4.2.1. Paso de parámetros a través de registro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

8.4.2.2. Paso de parámetros a través de memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

8.4.2.3. Paso de parámetros a través de la pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156

8.4.2.4. Almacenamiento de variables locales a una subrutina . . . . . . . . . . . . . . . . . . . . . . 157

8.5. Gestión del bloque de activación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

8.6. Ejemplo de evolución del bloque de activación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158

8.7. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

Page 8: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

8 / 198

A. Subconjunto de instrucciones de la arquitectura IA-32 165

A.1. Nomenclatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

A.2. Instrucciones de movimiento de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

A.2.1. MOV: Movimiento de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165

A.2.2. PUSH: Instrucción de carga sobre la pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

A.2.3. POP: Instrucción de descarga de la pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

A.2.4. XCHG: Instrucción de intercabmio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

A.3. Instrucciones aritméticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

A.3.1. ADD: Instrucción de suma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

A.3.2. SUB: Instrucción de resta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167

A.3.3. INC: Instrucción de incremento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

A.3.4. DEC: Instrucción de decremento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

A.3.5. NEG: Instrucción de cambio de signo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

A.3.6. MUL: Instrucción de multiplicación sin signo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169

A.3.7. DIV: Instrucción de división sin signo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

A.3.8. IMUL: Instrucción de multiplicación con signo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

A.3.9. IDIV: Instrucción de división con signo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

A.4. Instrucciones lógicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

A.4.1. AND: Instrucción de conjunción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

A.4.2. OR: Instrucción de disyunción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173

A.4.3. XOR: Instrucción de disyunción exclusiva . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173

A.4.4. NOT: Instrucción de negación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

A.5. Instrucciones de desplazamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

A.5.1. SAL/SAR: Desplazamiento aritmético . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

A.5.2. SHL/SHR: Desplazamiento lógico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175

A.5.3. RCL/RCR: Instrucción de rotación con acarreo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176

A.5.4. ROR/ROL: Instrucción de rotación sin acarreo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

A.6. Instrucciones de salto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

A.6.1. JMP: Instrucción de salto incondicional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

A.6.2. Jcc: Instrucciones de salto condicional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

A.6.3. CALL: Instrucción de llamada a subrutina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179

A.6.4. RET: Instrucción de retorno de subrutina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

A.7. Instrucciones de comparación y comprobación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

A.7.1. CMP: Instrucción de comparación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

A.7.2. TEST: Instrucción de comprobación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180

Page 9: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

9 / 198

B. El depurador 182

B.1. Arranque y parada del depurador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185

B.2. Visualización de código . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186

B.3. Ejecución controlada de un programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186

B.4. Visualización de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189

B.5. Ejercicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192

B.6. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193

C. Licencia Creative Commons 194

Page 10: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

10 / 198

Índice de figuras

1.1. Perspectiva del programador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1.2. Perspectiva del diseñador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.3. Diferentes perspectivas de un ordenador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1.4. Relación entre los niveles de abstracción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

1.5. Estructura de un ordenador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

1.6. Creación de un ejecutable en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

1.7. Creación de un ejecutable a partir de un programa en lenguaje ensamblador . . . . . . . . . . . . . . . . . . . . 24

1.8. Introducción el comando programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

1.9. Copia del ejecutable de disco a memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

1.10. Ejecución de la primera instrucción de un programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

2.1. Rango de enteros codificados por 8 bits en signo y magnitud . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

2.2. Rango de enteros codificados por 8 bits en complemento a 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

2.3. Estructura de la representación binaria en coma flotante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

2.4. Estructura de las instrucciones de ual-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

2.5. Formato de codificación del conjunto ual-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

2.6. Ejemplo de codificación de instrucción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

2.7. Estructura de las instrucciones de ual-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

2.8. Estructura de la correspondencia de ual-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

2.9. Codificación de los operandos en ual-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

2.10. Formato de la codificación de ual-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

3.1. Estructura de la memoria RAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

3.2. Operaciones sobre memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

3.3. Señales que conectan el procesador y la memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

3.4. Memoria real y posible en un procesador con arquitectura IA-32 . . . . . . . . . . . . . . . . . . . . . . . . . . 56

3.5. Almacenamiento de booleanos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

3.6. Almacenamiento de un string . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

3.7. Almacenamiento de enteros en memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

3.8. Interpretación de bytes en little endian y big endian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

3.9. Almacenamiento de instrucciones en formato fijo y variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

Page 11: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

11 / 198

3.10. Acceso a memoria en grupos de 4 bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

3.11. Acceso doble para obtener 4 bytes consecutivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

3.12. Dirección de un elemento de una tabla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

3.13. Ejemplo de almacenamiento de una tabla de enteros de 32 bits en memoria . . . . . . . . . . . . . . . . . . . . . 64

3.14. Almacenamiento de una tabla de seis enteros en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

3.15. Dirección de memoria almacenada como número natural . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

3.16. Una posición de memoria ‘apunta a’ otra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

3.17. Indirección múltiple para acceder a un dato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67

3.18. Tabla con direcciones de comienzo de strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

3.19. Dos referencias en Java que apuntan al mismo objeto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

3.20. Acceso a un dato mediante doble indirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

4.1. Pentium 4 Northwood (Dic. 2001). Fuente: Intel Technology Journal, vol. 6, núm. 2. . . . . . . . . . . . . . . . 73

4.2. Chip con un procesador Pentium 4 en su interior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

4.3. Tipos de datos del procesador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

4.4. Acceso alineado a memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

4.5. Registros de propósito general . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

4.6. Registro de estado y control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

4.7. Contador de programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

4.8. Ciclos de ejecución de varias instrucciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

4.9. Fase de fetch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

4.10. Fase de decodificación inicial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

4.11. Fase de decodificación final . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

4.12. Fase de ejecución . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

4.13. Fase de escritura de resultado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

4.14. Ciclo de ejecución de instrucciones de coma flotante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

4.15. Efecto de la instrucción push . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

4.16. Efecto de la instrucción pop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

4.17. Ejecución de instrucciones de pila . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

4.18. Valores de la cima para la pila vacía y llena . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

5.1. Formato de Instrucción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

5.2. Byte ModR/M de las instrucciones de la arquitectura IA-32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

5.3. Byte SIB de las instrucciones de la arquitectura IA-32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

5.4. Codificación de una instrucción ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

5.5. Desplazamiento aritmético de 1 bit en un número de 8 bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

5.6. Rotación de un operando de 8 bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

6.1. El programa ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

6.2. Estructura de un programa en ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

Page 12: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

12 / 198

6.3. Etiqueta y direcciones relativas a ella . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114

7.1. Dirección de un elemento en una tabla de enteros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

7.2. Funcionalidad de los modos de direccionamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

7.3. Acceso a operando con modo inmediato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

7.4. Acceso a operando con modo registro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

7.5. Acceso a operando con modo absoluto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125

7.6. Acceso a operando con modo registro indirecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

7.7. Acceso a operando con modo auto-incremento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128

7.8. Acceso a operando con modo auto-decremento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129

7.9. Acceso a operando con modo base + desplazamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

7.10. Acceso a operando con modo base + índice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132

7.11. Acceso a operando con modo índice escalado + desplazamiento . . . . . . . . . . . . . . . . . . . . . . . . . . 134

7.12. Acceso a operando con modo base + índice escalado + desplazamiento . . . . . . . . . . . . . . . . . . . . . . 136

7.13. Definición de una matriz de enteros almacenada por filas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

7.14. Circuito para el cálculo de la dirección efectiva . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

8.1. Compilación de un programa escrito en un lenguaje de alto nivel . . . . . . . . . . . . . . . . . . . . . . . . . . 142

8.2. Referencia a símbolos en dos ficheros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

8.3. Reubicación de símbolos en la fase de entrelazado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

8.4. Estructura de un if/then/else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

8.5. Traducción de un if/then/else a ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145

8.6. Estructura de un switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

8.7. Traducción de un switch a ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147

8.8. Estructura de un bucle while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

8.9. Traducción de un bucle while a ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

8.10. Estructura de un bucle for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

8.11. Traducción de un bucle for a ensamblador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

8.12. Llamada y retorno de una subrutina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152

8.13. Invocación anidada de subrutinas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153

8.14. Parámetros y resultado de una subrutina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154

8.15. Evolución de la pila desde el punto de vista del programa llamador . . . . . . . . . . . . . . . . . . . . . . . . 160

8.16. Evolución de la pila durante la llamada a cuenta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162

B.1. Primer caso en el que realmente se encuentra un bug (Fuente: U.S. Naval Historical Center Photograph) . . . . . 183

Page 13: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

13 / 198

Índice de tablas

2.1. Potencias de 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

2.2. Conversión de binario a decimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

2.3. Correspondencia entre grupos de 3 bits y dígitos en octal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

2.4. Traducción de binario a octal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

2.5. Correspondencia entre grupos de 4 bits y dígitos en hexadecimal . . . . . . . . . . . . . . . . . . . . . . . . . . 34

2.6. Traducción de binario a hexadecimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

2.7. Ejemplo de codificación de enteros en signo y magnitud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

2.8. Representación de números naturales y enteros en binario con n bits . . . . . . . . . . . . . . . . . . . . . . . . 37

2.9. Parámetros del formato IEEE 754 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

2.10. Rangos representados en los formatos simple y doble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

2.11. Ejemplo de símbolos codificados con Unicode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

2.12. Texto de un programa y su codificación en ASCII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

2.13. Representación en hexadecimal de símbolos de ual-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

2.14. Codificación del operando lugar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

2.15. Representación en binario y hexadecimal de símbolos de ual-2 . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

2.16. Ejemplos de codificación de operandos en ual-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

2.17. Codificación de instrucciones de ual-3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

3.1. Unidades de almacenamiento de información en bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

3.2. Tipos de datos básicos en el lenguaje Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

4.1. Nomenclatura para los tamaños de información . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

5.1. Instrucciones con diferentes tipos de operandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

5.2. Instrucciones con sufijos de tamaño . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

5.3. Instrucciones de transferencia de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98

5.4. Instrucciones aritméticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

5.5. Instrucciones de multiplicación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

5.6. Instrucciones de división . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

5.7. Instrucciones lógicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

5.8. Instrucciones de desplazamiento aritmético . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

Page 14: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

14 / 198

5.9. Instrucciones de rotación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

5.10. Instrucciones de salto condicional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104

5.11. Resta y bit de desbordamiento de dos enteros de 2 bits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

5.12. Secuencias de instrucciones de comparación y salto condicional . . . . . . . . . . . . . . . . . . . . . . . . . . 107

5.13. Secuencias de instrucciones de comprobación y salto condicional . . . . . . . . . . . . . . . . . . . . . . . . . 107

7.1. Modos de direccionamiento de la arquitectura IA-32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

8.1. Pasos para la gestión del bloque de activación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159

A.1. Opciones de la multiplicación sin signo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

A.2. Opciones de la división sin signo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170

A.3. Opciones de la división con signo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

B.1. Programa en ensamblador utilizado como ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

Page 15: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

15 / 198

Capítulo 1

Ejecución de programas en un ordenador

En este capítulo se describen las diferentes formas posibles de percibir un ordenador y su funcionamiento. El usuario común lopercibe como una máquina capaz de ejecutar ciertas órdenes o comandos que se le comunican utilizando los dispositivos talescomo teclado, ratón, etc. Pero para la persona con nociones básicas de electrónica digital, el ordenador es un circuito complejo quepermite la ejecución de ciertos comandos sencillos. ¿Cómo es posible que el mismo objeto sea percibido de forma tan diferente?Esto es debido a que existen varios niveles desde los que se puede analizar la estructura de un ordenador. Cuando el usuarioconvencional introduce un comando por teclado, el ordenador lo ejecuta mediante un número muy elevado de instruccionesbásicas que permiten la comunicación con los diferentes dispositivos para obtener los datos así como las operaciones básicas enel interior del procesador. Se verá cómo tareas comunes solicitadas por un usuario requieren la participación de varias partes delordenador.

1.1. Perspectivas de un ordenador

Un ordenador es un objeto que se puede percibir de múltiples formas, y todas ellas correctas. Cuando un usuario se sienta frentea uno de ellos y comienza a trabajar, el ordenador se percibe como un objeto que permite manipular una serie de programas quea su vez realizan una serie de tareas. Por ejemplo, al conectarse a Internet y entrar en un chat, el ordenador permite, a través delprograma de chat, el intercambio de mensajes con un conjunto de personas que a su vez están utilizando ese mismo programaen otros ordenadores en otros lugares. Pero además de utilizar el programa de chat, no se debe olvidar que se se está utilizandoigualmente la pantalla para visualizar los mensajes, el teclado para introducir su texto, y posiblemente el ratón para seleccionariconos o ventanas en la pantalla.

Otro ejemplo de utilización del ordenador es cuando un usuario abre un fichero de texto y comienza a escribir una carta. Elordenador facilita el trabajo de escritura y almacenamiento de este documento que puede incluir elementos especiales tales comoimágenes, diferentes tipos de letras, gráficas con datos, etc. Para realizar esta tarea también se utiliza la pantalla para visualizarlos datos, el teclado para introducir texto, y el ratón para realizar tareas de selección y manipulación de texto. Si este documentocreado de forma electrónica se necesita en papel, el ordenador permite enviarlo a una impresora que se encarga de plasmar enpapel lo que hasta el momento se había mostrado en pantalla.

Tanto la utilización de un programa de chat como la redacción e impresión de una carta son tareas que han sido previamenteintroducidas o programadas en el ordenador y por tanto puede ejecutarlas cuando el usuario así lo requiera. Pero los ordenadoresposeen una propiedad que los hace realmente potentes: se pueden programar con tareas nuevas. Es decir, si un ordenador nodispone del programa necesario para realizar una tarea, y ésta es programable, existen lenguajes de programación tales comoJava que permiten escribir estos programas e instalarlos. A partir de ese momento, el ordenador podrá ejecutar el programaescrito tantas veces como el usuario desee.

Pero estos lenguajes de programación, a pesar de que sirven para conseguir que el ordenador realice una tarea concreta, noson los que el ordenador entiende directamente. Antes de instalar un programa es preciso traducirlo al lenguaje básico que semaneja internamente. A este proceso de traducción se le denomina compilación. Según el diccionario de la lengua española, lapalabra compilar significa ‘preparar un programa en el lenguaje máquina a partir de otro programa de ordenador escrito en otrolenguaje’. Una vez que el programa ha sido traducido o compilado, el ordenador ya puede ejecutarlo. Esta forma de utilizar unordenador, como un objeto al que podemos darle órdenes precisas sobre tareas, mediante un programa escrito en un lenguaje

Page 16: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

16 / 198

de programación, y que se traduce al lenguaje máquina interno del ordenador, es lo que denominaremos la ‘perspectiva delprogramador’. La figura 1.1 muestra de forma gráfica los elementos de la perspectiva del programador.

Figura 1.1: Perspectiva del programador

Pero además de los ejemplos cotidianos de uso, es posible percibir un ordenador desde una perspectiva totalmente diferente. Enefecto, si se dispone de nociones básicas de electrónica digital, se sabe que en su interior hay una serie de circuitos electrónicosinterconectados entre sí. Si se abre la caja de un ordenador puede verse todo un conjunto de pequeños circuitos interconectadospor infinidad de cables que atraviesan una superficie rígida conocido genéricamente con el nombre de ‘placa’. Los circuitos, asu vez están diseñados utilizando puertas lógicas, que a su vez constan de un conjunto de transistores. La manera en que dichaspuertas lógicas están conectadas permite realizar operaciones aritméticas básicas tales como sumas, restas, multiplicaciones,divisiones, etc. Al igual que todo circuito electrónico, se necesita un cierto voltaje para que funcione que es proporcionado porotro circuito que es conocido como la fuente de alimentación y que forma parte del ordenador.

Si se observa con más detalle la estructura interna de un ordenador, es posible distinguir algunos de sus componentes. Los discosduros suelen tener aspecto de caja metálica rectangular con conectores en uno de sus lados. Puede verse cómo algunos de losconectores que aparecen en la parte posterior de la caja del ordenador están conectados a pequeñas placas con circuitos impresosque a su vez están conectadas a una placa mayor que ocupa casi la totalidad de la carcasa.

De todos los circuitos o componentes presentes en el ordenador, hay uno especialmente importante. Se distingue, en la mayoría delos ordenadores, porque es el circuito de mayor tamaño en el equipo y requiere su propio ventilador para evitar recalentamientospor lo que no suele estar directamente visible. Este circuito es el que se conoce con el nombre de procesador, y es el responsablede dirigir, controlar y ejecutar las principales tareas que realiza el ordenador. La característica fundamental de este procesadores que puede ejecutar programas en lenguaje máquina. Por tanto, el lenguaje máquina es aquél que consta de las instrucciones ocomandos que son entendidos por el procesador.

Recordemos que una de las principales capacidades del ordenador es la de ejecutar programas, y una gran parte de esta capacidadse debe a la presencia del procesador. Esta perspectiva del ordenador como un conjunto de circuitos electrónicos interconectadosentre sí se denominará la perspectiva del diseñador. La figura 1.2 muestra algunos de los elementos de los que consta estaperspectiva.

Page 17: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

17 / 198

Figura 1.2: Perspectiva del diseñador

Una vez vistas estas dos perspectivas posibles, ¿cómo puede un equipo formado por estos componentes electrónicos permitirnostareas tales como, por ejemplo, comprar por Internet?

La respuesta a esta pregunta es larga y sobre todo compleja, y por ello debe ser tratada en diferentes fases. En lo que resta deeste documento se ofrece parte de la respuesta a dicha pregunta mediante la explicación del funcionamiento de un procesadordesde el punto de vista de su programación en lenguaje máquina. La programación en lenguajes como Java es posible porque losprogramas se compilan y se obtiene el lenguaje máquina que el procesador es capaz de ejecutar.

El objetivo, por tanto es ofrecer una tercera visión de un ordenador que se encuentra entre la perspectiva del diseñador y la deusuario. El estudio del ordenador se centra alrededor del procesador y su lenguaje máquina, que es capaz de ofrecer la funciona-lidad necesaria para ejecutar los programas diseñados en lenguajes tales como Java. La figura 1.3 ilustra la nueva perspectiva aestudiar con respecto a las dos anteriores.

Figura 1.3: Diferentes perspectivas de un ordenador

1.2. Niveles de abstracción

Generalmente, en entornos científicos, cuando se estudia un problema demasiado complejo se utilizan mecanismos que permitansimplificarlo pero que a la vez se muestren sus aspectos más relevantes. A este proceso de simplificación, en el que ciertosaspectos se ocultan reduciendo así su complejidad, se le denomina abstracción

Para ilustrar el proceso de abstracción se puede tomar como ejemplo el problema de buscar un edificio en cualquier lugar delmundo mediante su dirección de correo postal. Las direcciones de correo postal incluyen el país en el que se encuentra eldestinatario. En un primer nivel de búsqueda, se toma la información referida a todos los países del mundo y se selecciona el paísespecificado en la dirección. En una segunda fase, se obtiene la información sobre la división interna de un país (estas divisionespueden tener diferentes nombres tales como comunidades, provincias, departamentos, estados, etc.) Una vez localizada la unidadterritorial se debe seleccionar una ciudad. Para ello, tan sólo es preciso obtener la información de ciudades incluidas en la unidadterritorial bajo consideración y localizar la del destinatario. Finalmente, dentro de la ciudad se debe obtener la información sobrelas calles y sus números para conocer la posición exacta del edificio que se busca.

La información manipulada durante este proceso se puede dividir en varias categorías:

Page 18: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

18 / 198

Información sobre todos los países del mundo.

Unidades territoriales dentro del país seleccionado.

Ciudades dentro de la unidad seleccionada.

Calles dentro de la ciudad seleccionada.

Números dentro de la calle seleccionada.

Entre estas categorías existe una relación muy intuitiva. Cada una de ellas contiene detalles de la siguiente categoría. La infor-mación sobre todos los países del mundo puede incluir además todas las divisiones en unidades territoriales. De igual forma, losdatos sobre todas las ciudades de una unidad territorial puede incluir todas sus calles. Sin embargo, la solución del problema delocalizar un edificio se simplifica sustancialmente si los datos están divididos en las categorías antes mencionadas, es decir, unacategoría incluye la información de su nivel e ignora o abstrae los datos del resto de categorías.

Se puede decir que como cada una de estas categorías ignora detalles de las categorías siguientes, simplifica la informaciónacerca de la localización de edificios en el mundo pero, a la vez, conservando los aspectos más relevantes. Cada una de estascategorías puede ser considerada como un nivel de abstracción.

Generalizando este concepto, los niveles de abstracción son diferentes visiones de una misma entidad relacionadas de tal formaque cada una de ellas provee más detalle que el nivel anterior, pero ignora detalles del nivel siguiente. Como conclusión, entrelos niveles de abstracción se puede establecer una relación con respecto a dos aspectos: la complejidad y el detalle. La figura1.4 ilustra un ejemplo con cuatro niveles y cómo la complejidad y el detalle se relacionan de manera inversa. A mayor nivel decomplejidad, mayor número de detalles, y cuanto menos complejo es el resultado de una abstracción, menos detalles incluye.

Figura 1.4: Relación entre los niveles de abstracción

Un segundo ejemplo de los diferentes niveles de abstracción es la escala de un mapa topográfico. Un mapa es una representaciónde algunos de los aspectos contenidos en una determinada área. El tamaño del mapa y el de dicha área están relacionadosmediante un factor de escala. Es posible tener mapas de la misma área pero realizados a diferente factor de escala. Estos mapasofrecen diferentes visiones del lugar pero con diferentes niveles de complejidad y detalle.

La observación clave de estos dos ejemplos es que la resolución de problemas en un ámbito concreto es posible representando larealidad mediante un nivel de abstracción adecuado. Por ejemplo, si una empresa de distribución de mercancías a nivel mundialnecesita decidir dónde situar sus centros de distribución, no es preciso que utilice la información de qué números hay en cadacalle. Igualmente, un ingeniero que desea diseñar una autopista no puede utilizar un mapa con una escala tan grande que no seperciban lo suficiente los accidentes orográficos.

1.2.1. Estudio de un procesador a nivel lenguaje máquina

En el caso del estudio de un procesador y de su integración en un ordenador, existen múltiples niveles de abstracción y cada unode ellos contiene diferentes tipos de detalles. A nivel más detallado, un procesador funciona como un circuito electrónico en elque las intensidades de corriente y los voltajes van cambiando en diferentes partes consiguiendo así su correcto funcionamiento.Estas corrientes y voltajes son, a su vez, movimientos de electrones a nivel atómico del material semiconductor del que estáhecho el procesador. En el otro extremo se puede estudiar el ordenador en su totalidad a través de las tareas que puede ejecutar yla comunicación a través de sus dispositivos.

Page 19: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

19 / 198

De entre estos dos niveles de abstracción, el estudio que se presenta en este documento está realizado a nivel del lenguaje máquinaque el procesador es capaz de ejecutar. Para clarificar más los detalles que forman parte de este nivel los compararemos con losniveles de abstracción adyacentes.

En un nivel más abstracto se puede situar la ejecución de programas en lenguajes de alto nivel tales como Java. Las instruccionesque se escriben son más sofisticadas (bucles, condicionales, comparaciones, etc) y se ciñen a una sintaxis específica de dicholenguaje. Nótese que un mismo procesador puede ejecutar programas escritos en diferentes lenguajes de programación. Tan sóloes preciso utilizar un procedimiento de compilación adecuado para traducir estos lenguajes al lenguaje máquina del procesador.A lo largo de los siguientes capítulos se harán breves incursiones desde el lenguaje máquina hasta este nivel de abstracción conel propósito de ilustrar el proceso de compilación.

En un nivel de abstracción más detallado del lenguaje máquina se encuentra la estructura interna del procesador. Estos detallesson imprescindibles para entender cómo se ejecutan paso a paso las diferentes instrucciones que forman parte del lenguajemáquina. Basándose en la estructura interna de un procesador se puede entender, por ejemplo, el tiempo que tarda éste enejecutar una determinada instrucción así como los circuitos que utiliza. Análogamente al nivel de abstracción anterior, en lossiguientes capítulos se mencionarán algunos detalles de este nivel para facilitar la comprensión de cómo el procesador ejecutalas instrucciones en lenguaje máquina.

1.3. Estructura de un ordenador

La estructura interna o arquitectura de un ordenador varía enormemente de unos modelos a otros sobre todo de la tarea a la queesté orientado el equipo. Así, un ordenador de los denominados ‘personales’, es decir, orientado a realizar tareas relativas a unapersona, puede tener una estructura diferente a un ordenador que utilizado para el almacenaje masivo y acceso al conjunto dedatos de una empresa.

Como es imposible mostrar la gran variedad de arquitecturas que existen hoy en día en el mercado de ordenadores, se ha op-tado por presentar un modelo simplificado de la arquitectura de un ordenador personal, también conocido como PC que es laabreviatura del término inglés personal computer. La figura 1.5 ilustra este modelo.

Page 20: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

20 / 198

Figura 1.5: Estructura de un ordenador

Todo ordenador tiene, como parte fundamental de su arquitectura, al menos un procesador. En su interior se encuentran una seriede elementos básicos tales como registros (capaces de almacenar pequeñas cantidades de información), unidad aritmético-lógicao UAL (capaz de realizar simples operaciones aritméticas), unidad de control, etc. Este procesador se comunica con el resto delordenador a través de lo que denominaremos el bus del sistema.

La comunicación entre el procesador y el resto del equipo se puede dividir a su vez en dos categorías: la conexión con la memoria(también llamada memoria principal o memoria RAM), y la conexión con los dispositivos de entrada salida (E/S). El circuitorepresentado en la figura 1.5 por el nombre Puente E/S es el encargado de separar los datos de estas categorías. La conexión conla memoria RAM se realiza a través del bus de memoria. Esta memoria es capaz de almacenar información mientras el equipoesté encendido. Al apagar el equipo, los datos almacenados en este dispositivo se pierden, por este motivo, también se le conocecomo memoria volátil.

Los datos dirigidos a los dispositivos de entrada/salida se envían a través del bus de entrada/salida (o bus E/S). Este bus seutiliza para conectar todos los dispositivos auxiliares que necesita el ordenador para su funcionamiento. Dichos dispositivos nose conectan directamente el bus, sino a un circuito encargado de gestionar su comunicación denominado ‘controlador’.

Los dispositivos más comunes presentes en la mayoría de los ordenadores personales son el teclado, el ratón, la pantalla y eldisco duro. Teclado y ratón son dos dispositivos de entrada de datos (el ordenador sólo recibe datos de ellos), la pantalla es desalida de datos, y el disco duro es de entrada y salida de datos (se realizan operaciones de lectura y escritura). Este disco tieneuna funcionalidad similar a la memoria RAM, es decir, almacenar datos, pero con la diferencia de que si se apaga el equipo, lainformación permanece almacenada sin alteraciones. A los dispositivos con esta propiedad (disco duro, CD-ROM, DVD, etc.) seles denomina memoria no volátil.

Una de las características que ha contribuido a que esta arquitectura haya alcanzado un nivel tan alto de popularidad es laposibilidad de conectar de forma sencilla dispositivos adicionales. El bus de entrada/salida está preparado para conectar másdispositivos y así dotar al ordenador de mayor capacidad. De esta forma, el ordenador se puede completar con una impresora, unscanner, discos duros adicionales, lector/grabador de DVDs, etc. La mayoría de estos dispositivos se conectan al ordenador ya

Page 21: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

21 / 198

sea a través de conectores específicamente incluidos a tal efecto (tal es el caso de la conexión de una impresora al puerto paralelo)o a través de las clavijas de expansión.

1.4. Definición de un programa

Un programa es un conjunto de órdenes o instrucciones por las que un ordenador realiza diversas funciones. Los programas estánescritos en un lenguaje de programación mediante la utilización de un editor.

Tómese como ejemplo el programa escrito en el lenguaje de programación Java que se muestra en el ejemplo 1.1. En él se puedenapreciar detalles comunes a cualquier programa.

Ejemplo 1.1 Programa en Java

// Definición de la clase Programapublic class Programa {

// Definición del método mainpublic static void main(String[] args) {

String mensaje;

// Inicialización del mensaje a imprimirmensaje = new String("Este es mi primer programa");

// Imprimir el mensajeSystem.out.println(mensaje);

} // Final del método main} // Final de la clase Programa

La primera observación es que, tal y como se ha dicho anteriormente, las palabras que se utilizan y su significado están estipuladaspor la definición del lenguaje de programación Java. Todo programa define un conjunto de órdenes a ejecutar sobre un conjuntode datos, por lo que además de las órdenes, también se incluyen en un programa la definición de los datos a utilizar (en el ejemploes la definición de una variable con nombre mensaje).

El primer paso para que el ordenador ejecute las órdenes contenidas en un programa es escribir su contenido en un fichero. En elcaso concreto de Java, este fichero ha de contener lo que se denomina texto plano, es decir, un fichero que contenga únicamente eltexto sin información de formato, márgenes, imágenes, etc. Supongamos que este fichero tiene por nombre Programa.java.

El siguiente paso es lo que se denomina la compilación del programa y consiste en traducir el fichero Programa.java allenguaje que el procesador es capaz de entender, es decir, a lenguaje máquina. En general, este proceso de traducción consiste envarios pasos o etapas que son realizadas por varios programas diferentes. Existen lenguajes de programación y ordenadores enel que el proceso de compilación se realiza en un único paso y por un único programa, y otros en los que se requieren múltiplespasos y cada uno de ellos lo realiza un programa diferente. En el ejemplo del programa Java, el proceso de traducción a lenguajemáquina se ilustra en la figura 1.6.

Page 22: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

22 / 198

Figura 1.6: Creación de un ejecutable en Java

En general, no todos los ficheros temporales resultantes de las diferentes etapas de traducción o compilación son visibles alusuario. En el caso de un programa Java, tal y como ilustra la figura 1.6 se utiliza la herramienta javac que a partir de un ficherofuente produce un fichero temporal con extensión .class. A partir de este fichero, la herramienta java realiza la traducción quefalta y procede a su ejecución. En este ejemplo, ambas herramientas se invocan a través de un intérprete de comandos.

1.5. El lenguaje ensamblador

El procesador que contiene todo ordenador es capaz de ejecutar un conjunto de instrucciones definidas en el lenguaje máquina.La forma de definir estas instrucciones, al igual que el resto de información contenida en un ordenador, es mediante la utilizaciónde ceros y unos. En otras palabras, todas las instrucciones que es capaz de ejecutar un procesador se deben codificar medianteceros y unos de una forma específica e inequívoca. Se puede decir, por tanto, que el lenguaje del procesador es el lenguajemáquina.

Al igual que en el caso de Java, es posible escribir programas en lenguaje ensamblador para que sean ejecutados por el procesador.Pero escribir un programa de estas características es impensable, puesto que no sería más que una sucesión de ceros y unoscodificando los datos y las órdenes del programa. Para facilitar esta tarea se define el lenguaje ensamblador que no es más queuna representación de las instrucciones y datos del lenguaje máquina pero utilizando letras y números en lugar de la lógica binaria(ceros y unos).

La traducción del lenguaje ensamblador a lenguaje máquina se realiza con un programa encargado de producir la codificación enceros y unos del programa para su posterior ejecución. Dada la proximidad entre estos dos lenguajes, a menudo sus nombres seutilizan de manera indistinta.

El ejemplo 1.2 muestra un sencillo programa escrito en lenguaje ensamblador de la arquitectura IA-32®. En los siguientescapítulos se hace un estudio más detallado del lenguaje máquina de esta arquitectura así como de sus principales características.

Page 23: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

23 / 198

Por el momento, es suficiente saber que el código máquina mostrado corresponde a dicha arquitectura. De la mera inspecciónvisual de este programa se pueden deducir varios aspectos de la programación en lenguaje ensamblador.

Ejemplo 1.2 Programa en ensamblador

1 .data # Comienza sección de datos2 mensaje:.asciz "Este es mi primer programa\n" # Mensaje a imprimir3

4 .text # Comienza la sección de código5 .globl main # Declaración de main como símbolo6 # global7 main:8 push %ebp # Bloque de activación9 mov %esp, %ebp

10

11 push $mensaje # mueve un dato a la pila12

13 call printf # printf es una función que14 # imprime por pantalla los15 # datos que recibe16

17 add $4, %esp # borra la cima de la pila18

19 mov %ebp, %esp # Deshacer bloque de activación20 pop %ebp21 ret # termina el programa

El programa consta de dos secciones claramente diferenciadas. La primera de ellas comienza a partir de la palabra .data y esla sección de datos tal y como lee el comentario que se encuentra a continuación. En ella podemos encontrar la definición delos datos que van a ser utilizados por el programa. Nótese cómo se define un mensaje mediante la utilización de los símbolosmensaje y .asciz.

La segunda sección comienza a partir de la palabra .text como indica el comentario en la misma línea. A continuaciónencontramos una línea en la que el símbolo main se define como global (sin saber qué quiere decir esto). Lo más revelador delprograma se encuentra a partir de este punto, pues aparece la palabra main seguida por cuatro líneas que se corresponden concuatro instrucciones del lenguaje máquina del procesador.

El punto del código en el que se encuentra la palabra main: corresponde con el punto de arranque del programa. A continuación,se encuentran varias instrucciones máquina. Estas instrucciones son extremadamente cortas, constan de una única palabra (tal esel caso de la última línea) o de una palabra seguida de una o dos más separadas por comas. Estas instrucciones pueden incluirpalabras que aparecen previamente en el texto (por ejemplo push $mensaje), números (por ejemplo add $4,%esp), asícomo otros identificadores.

Además, y mediante la interpretación de los comentarios incluidos al final de cada línea, se puede deducir que el programaimprime un mensaje por pantalla, y para eso utiliza una función denominada printf.

Si se compara el programa ensamblador del ejemplo 1.2 con el programa Java del ejemplo 1.1, las diferencias son aparentes.La sintaxis, el tipo de instrucciones y la definición de datos son radicalmente diferentes. Lo que sí tienen ambos programasen común es que contienen un conjunto de órdenes y los datos utilizados. Aunque en estos dos ejemplo no es aparente, elnivel de abstracción que ofrecen estos dos lenguajes con respecto al lenguaje máquina es muy diferente. Mientras el lenguajeensamblador es prácticamente idéntico al lenguaje máquina, el lenguaje Java, por el contrario, ofrece construcciones que seaproximan a construcciones complejas orientadas a ser entendidas por un humano. A este tipo de lenguajes se les denominalenguajes de alto nivel. Como consecuencia, el proceso de traducción y producción de un ejecutable es mucho más fácil para elprograma escrito en ensamblador que para el escrito en Java.

1.5.1. Programación en lenguaje ensamblador

Los lenguajes de alto nivel ofrecen construcciones complejas y potentes para escribir las órdenes de un programa que sonluego traducidas a lenguaje máquina y ejecutadas por el procesador. Por otro lado, el lenguaje ensamblador no es más que una

Page 24: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

24 / 198

representación textual del lenguaje máquina. ¿Qué ventaja tiene escribir un programa en lenguaje ensamblador pudiendo utilizarun lenguaje de alto nivel como Java con su posterior proceso de compilación?

Esta pregunta se ha venido haciendo desde la aparición de los lenguajes de programación de alto nivel. La propia apariciónde estos lenguajes viene motivada, en parte, para evitar programas en lenguaje ensamblador pues suelen ser muy delicados deconstruir. Pero a pesar de ello, la programación en ensamblador sigue vigente en nuestros días. Sus ventajas son múltiples tal ycomo enumera Randall Bryant (ver [Bryant03]):

Requiere un conjunto de técnicas propias de cualquier ingeniero.

Para programar en ensamblador es imprescindible entender el funcionamiento de un procesador y esto a su vez facilita lacomprensión de un sistema completo (procesador, memoria, dispositivos, etc.)

Cada vez es más común encontrar dispositivos electrónicos que contienen un procesador.

Un diseñador de procesadores necesita estar familiarizado con los lenguajes máquina y su utilización en programas.

Entender el funcionamiento de un procesador y de su lenguaje máquina permite desarrollar programas extremadamente efi-cientes y robustos.

Es el único lenguaje que entiende el hardware.

1.5.2. Ejecución de un programa en ensamblador

Aunque el lenguaje ensamblador es prácticamente idéntico al lenguaje máquina, para crear un programa que sea ejecutado por elprocesador, se requiere un proceso de traducción o compilación. Este proceso consta de varios pasos que pueden ser realizadospor una o varias herramientas y que pueden producir ficheros temporales.

En los ejemplos que se muestran a continuación se asume que el ordenador de trabajo ejecuta el sistema operativo Unix (o Linux).Dicho sistema incluye un programa denominado ‘intérprete de comandos’ que permite la introducción de órdenes textuales parala ejecución de programas. La forma habitual de utilizar este programa es mediante una ventana en la que el intérprete muestra unmensaje denominado prompt y espera a que el usuario teclee la orden a ejecutar. Una vez introducido un comando, el intérpretelo ejecuta, y al terminar ofrece de nuevo el prompt y espera el siguiente comando. En adelante se utilizará el símbolo $ pararepresentar el prompt del intérprete de comandos.

La figura 1.7 ilustra un ejemplo de cómo se obtiene un programa ejecutable a partir de un fichero que contiene un programaescrito en lenguaje ensamblador. La compilación la realiza el programa gcc a la que se le proporciona una opción para que elejecutable se almacene en un fichero con nombre programa (texto -o programa). La ejecución de esta herramienta realizalos pasos que en la figura se representan por las cajas Ensamblador y Enlazador.

Figura 1.7: Creación de un ejecutable a partir de un programa en lenguaje ensamblador

Page 25: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

25 / 198

La herramienta gcc es capaz de realizar múltiples tareas y una de las cuales es la traducción y generación de ejecutables a partirde lenguaje ensamblador. La funcionalidad de esta herramienta se controla mediante opciones que se añaden a continuación desu nombre tal y como ilustra la figura 1.7. Además de esta traducción, gcc también es capaz de ejecutar los pasos de ensambladoy entrelazado de forma separada e incluso combinar múltiples ficheros de código para obtener un ejecutable.

La ejecución del programa obtenido no requiere herramienta alguna, simplemente se escribe su nombre a continuación del prompty comienza su ejecución.

1.6. Ejecución de un programa

En la sección anterior se ha ejecutado el programa previamente escrito en lenguaje ensamblador mediante el comando:

$ programaEste es mi primer programa$

Cuando el usuario introduce el nombre del fichero ejecutable programa, el procesador está ejecutando el intérprete de coman-dos. Cuando el usuario pulsa las teclas para escribir la palabra programa el teclado notifica al procesador de que se ha pulsadouna tecla, y este obtiene la letra del controlador y la muestra por pantalla. Este proceso se repite para cada una de las letrasmientras que el intérprete de comandos se encarga de almacenar la línea entera en un lugar de memoria (ver figura 1.8).

Figura 1.8: Introducción el comando programa

Cuando se pulsa el retorno de carro, el procesador obtiene esa letra del controlador de teclado, la muestra por pantalla y laalmacena en memoria. Pero el retorno de carro es la marca de final de comando que hace que el intérprete de comandos pase

Page 26: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

26 / 198

a procesar el comando. Para ello se explora la línea leída de teclado y detecta que se trata del nombre de un ejecutable. Acontinuación se obtiene el contenido de dicho ejecutable del disco duro y se almacena en memoria (ver figura 1.9).

Figura 1.9: Copia del ejecutable de disco a memoria

Esta transferencia de datos se realiza porque el procesador necesita tener el código y los datos necesarios para ejecutar unprograma en memoria principal en donde puede acceder a ellos directamente mediante instrucciones de su lenguaje máquina. Elacceso al disco duro, por el contrario, requiere la ejecución de múltiples instrucciones máquina para calcular el lugar del disco enel que se encuentran los datos solicitados y para programar el controlador de disco para que obtenga dichos datos y los depositeen memoria.

Una vez que el programa está almacenado en memoria, el procesador tiene anotado el lugar en el que está su primera instrucción.El último paso (tras una serie de preparativos que no interesan en este momento) es pasar a ejecutar la primera instrucción delprograma tal y como se muestra en la figura 1.10 que es push $mensaje. A partir de ese instante el procesador está ejecutandolas instrucciones escritas en el programa sobre los datos definidos.

Page 27: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

27 / 198

Figura 1.10: Ejecución de la primera instrucción de un programa

La última instrucción ejecutada es ret. Tras ello, el procesador continúa con la ejecución del intérprete de comandos que a suvez está diseñado para que cuando se termina la ejecución de un programa se vuelva a mostrar el prompt (el símbolo $) porpantalla. A lo largo de los pasos descritos el procesador ha ejecutado del orden de miles de instrucciones máquina, y entre ellas,aquellas contenidas en el fichero programa.s.

1.7. Ejercicios

1. ¿Cuál es la diferencia entre un lenguaje de programación como Java y el lenguaje máquina? ¿Cómo se denomina al procesode traducción de uno al otro? ¿Qué característica específica define al lenguaje máquina?

2. En la arquitectura de un ordenador personal, ¿qué dos tipos de comunicación realiza el procesador con el resto del equipo?

3. ¿Cuántos buses están presentes en la estructura básica de un ordenador personal? ¿Cuál es su propósito?

4. Describir para qué sirve la unidad aritmético-lógica de un procesador.

5. ¿Qué diferencia hay entre lenguaje máquina y lenguaje ensamblador? ¿Cuál de ellos es más fácil de entender por unhumano?

6. ¿Qué es el proceso de compilación? ¿Cuál es el resultado final que se produce? ¿Cuántas herramientas pueden tomar parteen este proceso?

Page 28: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

28 / 198

7. A la vista de las operaciones que realiza el procesador para ejecutar un proceso cuyo nombre introduce el usuario a travésde teclado, idear y describir una tarea en la que el ordenador tenga que procesar información obtenida a través de lasclavijas de expansión, el disco duro y la memoria.

8. Un procesador tiene un único lenguaje máquina, pero puede tener más de un lenguaje ensamblador, ¿por qué?

9. Los lenguajes máquina de los diferentes procesadores existentes en el mercado son la mayoría de ellos diferentes entresí. ¿Puede un fichero ejecutable de un procesador ser ejecutado en general en otro procesador con un lenguaje máquinadiferente? Justificar la respuesta.

10. Utilizando un motor de búsqueda en Internet buscar tres empresas fabricantes de procesadores y para cada una de ellas dosprocesadores diferentes que estén siendo comercializados.

1.8. Bibliografía

[Bryant03] Randal E. Bryant y David O’Hallaron, Computer Systems, A Programmer’s Perspective, Prentice Hall, copy-right © 2003 Prentice Hall, 0-13-034074-X.

Page 29: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

29 / 198

Capítulo 2

Codificación de la información

En este capítulo se estudian las técnicas de codificación de la información utilizadas por un procesador para poder manipularelementos tales como números naturales, enteros, reales, instrucciones, operandos, etc. Todo circuito digital trabaja con lógicabinaria, mediante la combinación de múltiples instancias de estos valores se puede construir un esquema de codificación quepermite manipular los datos básicos para realizar cálculos.

2.1. Lógica binaria

Los circuitos electrónicos digitales se caracterizan por manipular todas sus señales en dos estados posibles: cero y uno. La infor-mación que procesan estos circuitos, por tanto, debe ser representada por tantas unidades de información como sean necesarias,pero siempre y cuando tengan uno de los dos estados posibles. Estas unidades binarias de información se llaman ‘bits’. Loscircuitos digitales, por tanto, están diseñados para operar internamente con bits. Un procesador es un circuito digital capaz deejecutar un conjunto previamente definido de instrucciones sencillas que se denomina su ‘lenguaje máquina’.

Pero para la ejecución de este lenguaje máquina es preciso codificar todos los elementos utilizados (números, símbolos, operan-dos, etc) mediante lógica binaria. Esta codificación es la base para entender cómo un ordenador en cuyo interior sólo existencircuitos capaces de procesar bits puede realizar tareas mucho más sofisticadas.

2.1.1. Propiedades de una codificación binaria

Un esquema de codificación con bits se define mediante una relación entre los elementos a codificar y un conjunto de cadenasde bits. Cada elemento debe tener al menos una representación en binario, y cada posible cadena de bits, debe correspondera un elemento. Esta correspondencia debe cumplir una serie de propiedades mínimas para que sea utilizable por los circuitosdigitales. Lo más importante es saber de antemano el número de elementos a codificar. Los circuitos digitales sólo puedenmanipular códigos binarios de una cierta longitud máxima, y por tanto se debe fijar de antemano. Por ejemplo, si el circuitodebe manipular números naturales, se debe escoger de antemano qué subconjunto de estos números se van a utilizar, y de ahí sededuce el número de bits necesarios para su codificación.

Si se utiliza un único bit, se pueden representar únicamente dos elementos, uno con cada uno de los valores posibles, 0 y 1. Sise utilizan cadenas de dos bits, el número de combinaciones posibles aumenta a cuatro: 00, 01, 10, 11. Si el número de bits seincrementa en una unidad, se puede comprobar que el número de combinaciones se duplica pues se pueden obtener dos gruposde combinaciones, uno de ellos con el bit adicional a uno y el otro a cero.

Si con un solo bit se pueden codificar dos elementos, y por cada bit que se añade se duplica el número de combinaciones posible,se deduce por tanto que con n bits se pueden codificar un máximo de 2n elementos.

La fórmula anterior calcula el número de combinaciones posibles al utilizar n bits, pero si se dispone de un conjunto de Nelementos, ¿cuántos bits se necesitan para poder codificarlos en binario? Por ejemplo, se dispone de cinco elementos, ¿es posiblecodificarlos en binario con dos bits? ¿y con tres? ¿y con cuatro? Se precisa un número de bits tal que el número de combinacionesposibles sea mayor al número de elementos. En otras palabras, se precisan n bits siempre y cuando n satisfaga la ecuación 2.1.

Page 30: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

30 / 198

N ≤ 2n.

EQUATION 2.1: Relación entre el número de bits y las posibles combinaciones

Dado un conjunto de N elementos, el número mínimo de bits se obtiene mediante la ecuación 2.2.

n≥ dlog2 Ne

EQUATION 2.2: Número mínimo de bits necesarios para codificar N elementos

donde los símbolos de representan el entero mayor que el logaritmo obtenido. Por ejemplo, para codificar un conjunto con cincoelementos se debe cumplir n ≥ log25, y por tanto n ≥ 2.3219281, es decir, n ≥ 3.

Esta desigualdad establece un mínimo en el número de bits, pero no un máximo. Efectivamente, si en el ejemplo anterior en lugarde utilizar 3 bits se utilizan más, la codificación es igualmente posible. Para codificar los elementos hay que tener un mínimo decombinaciones binarias, pero se pueden tener combinaciones extras.

Las dos ecuaciones anteriores se pueden transformar en las dos reglas a tener en cuenta en la codificación binaria de elementos:

1. Con n bits se pueden codificar hasta un máximo de 2n elementos diferentes.

2. Para codificar N elementos se precisan como mínimo dlog2Ne bits.

2.2. Representación de números en diferentes bases

Antes de estudiar cómo se codifican los diferentes elementos con los que trabaja un procesador en binario es útil estudiar larepresentación de números naturales en diferentes bases. Los números naturales se escriben comúnmente utilizando 10 dígitos, olo que es lo mismo, en base 10. Dado un número el dígito de menos peso es aquel que corresponde a las unidades, o en general,el que se escribe más a la derecha. Análogamente, el dígito de más peso es el que se escribe más a la izquierda. Un númerorepresentado en base b cumple las siguientes condiciones:

Se utilizan b dígitos para representar el número, desde el 0 hasta el b-1.

Al número representado por (b - 1) le sigue el número 10.

Análogamente, al número máximo posible representado por n dígitos le sigue uno con n + 1 dígitos en el que el de más pesoes el 1 y el resto son todo ceros.

Las condiciones anteriores se cumplen para los números representados en base 10 donde los dígitos utilizados son del 0 al 9.Al número representado por el dígito de más valor (el 9) le sigue un número de dos dígitos con el segundo dígito de más valorseguido del cero (el 10), y al número máximo posible representado por cuatro dígitos (el 9999) le sigue uno con cinco dígitosque comienza por 1 seguido de cuatro ceros (el 10000).

El valor de un número se obtiene sumando cada uno de los dígitos multiplicado por un factor que representa su peso. Así, dederecha a izquierda, el primer dígito se llama unidades, el segundo decenas, el tercero centenas, y así sucesivamente. En base 10,el valor del número se obtiene multiplicando el dígito de las unidades por uno, el de las decenas por 10, el de las centenas por100, y así sucesivamente. Tal y como muestra el ejemplo 2.1 para el número 3214.

Ejemplo 2.1 Número como suma de potencias de 103214 = 3∗1000+2∗100+1∗10+4

Los factores por los que se multiplican cada uno de los dígitos son las sucesivas potencias de la base utilizada, en este caso 10.El mismo número se puede reescribir de la siguiente forma:

3214 = 3∗103 +2∗102 +1∗101 +4∗100.

Es decir, el número se obtiene multiplicando cada dígito por la base elevada a un exponente igual a la posición que ocupacomenzando por el de menos peso cuya posición es cero. La fórmula para obtener el valor del número 3214 se puede reescribiren general como:

Page 31: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

31 / 198

3214 = ∑3i=0(di ∗basei) = (d0 ∗100)+(d1 ∗101)+(d2 ∗102)+(d3 ∗103)

donde di representa el dígito que ocupa la posición i en el número. La fórmula es generalizable para cualquier base. El valor enbase 10 de un número de n dígitos escrito en base b se obtiene mediante la ecuación 2.3.

∑n−1i=0 (di ∗basei)

EQUATION 2.3: Valor de un número de n dígitos en base b

Por ejemplo, el equivalente en base 10 del número 6342 escrito en base 7 se puede obtener mediante la ecuación 2.3:

63427 =3

∑i=0

(di ∗7i)

= (2∗70)+(4∗71)+(3∗72)+(6∗73)= 2+28+147+2058= 223510.

Por tanto, el número 6342 en base 7, corresponde con el número 2235 representado en base 10. El número en base 7 no poseeningún dígito mayor que 6, pues dicha base utiliza sólo los dígitos del 0 al 6.

Al escribir números en diferentes bases aparece un problema de ambigüedad. El número 2235 del ejemplo anterior es el equiva-lente en base 10 del número 6342 escrito en base 7. Pero a su vez, 2235 es un número válido en base 7 (que es un número válidoen base 7 pues sus dígitos son todos menores que 7), aunque tiene otro valor equivalente en base 10. Para evitar la confusión, taly como muestra la ecuación anterior, cuando se manipulan números en diferentes bases se incluye la base en la que está escritoa la derecha y como un subíndice.

2.2.1. Traducción de un número a diferentes bases

La ecuación 2.3 permite obtener la representación en base 10 de un número en cualquier base. El proceso inverso, es decir, de unnúmero en base 10 obtener su equivalente en una base diferente, es preciso realizar una serie de divisiones sucesivas para obtenerlos nuevos dígitos comenzando por el de menos peso. El proceso se ilustra con un ejemplo.

Supongamos que se quiere calcular el equivalente en base 7 del número 867510. El dígito de menos peso de la nueva representa-ción se obtiene manipulando la ecuación 2.3:

∑n−1i=0 (di ∗basei) = d0 +(base∗∑

n−1i=1 (di ∗basei−1))

Si se divide la expresión anterior por la base se obtiene como resto el dígito de menos peso d0. El cociente contiene el resto dedígitos y al aplicar sucesivas divisiones se obtiene como resto los dígitos del número en orden creciente de significación.

Por ejemplo, considérese el número 867510. Para obtener su representación en base 7 se realiza la primera división cuyo resto es2, y por tanto su dígito de menos peso. El cociente resultante es 1239 que se vuelve a dividir por 7 y se obtiene un resto de 0 yun nuevo cociente de 177. Si se repite esta operación sucesivamente, el cociente obtenido será eventualmente 0, y los sucesivosrestos corresponden con la representación del número en base 7 tal y como muestra la ecuación 2.4

8675 = (1239∗7)+2= (((177∗7)+0)∗7)+2= (((((25∗7)+2)∗7)+0)∗7)+2= (((((((3∗7)+4)∗7)+2)∗7)+0)∗7)+2

EQUATION 2.4: Obtención de los dígitos en base 7

La aplicación sucesiva de divisiones por la base garantiza que el cociente alcanza siempre un valor menor al de la base. En cuantose da este caso no es preciso realizar ninguna división más. Se han obtenido los dígitos en base 7 pero la representación siguesiendo consistente con la ecuación 2.3 si se reorganizan los términos tal y como se muestra en la ecuación 2.4:

Page 32: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

32 / 198

que corresponde con la codificación en base 7 del número 8675, es decir, 867510=342027.

Como resumen, dado un número en base 10, su representación en base b se obtiene dígito a dígito comenzando por el de menospeso como resto de sucesivas divisiones por la base. El proceso se detiene cuando el cociente final es menor que la base.

Se han descrito los dos procedimientos para traducir un número representado en cualquier base a base 10, y viceversa. Combi-nando ambos procedimientos se pueden traducir números representados en cualquier base.

2.3. Codificación de números naturales

El conjunto de datos más simple de codificar en binario para que lo manipule un procesador es el de los números naturales. Larepresentación corresponde con los números en base 2. Los dos únicos dígitos de esta base coinciden con los dos valores quepueden manipular los circuitos digitales.

Dado un número binario con n dígitos, su equivalente en decimal se obtiene aplicando la ecuación 2.3:∑

n−1i=0 (di ∗2i).

Pero como los dígitos que pueden aparecer en un número binario son 0 o 1, la fórmula anterior se puede interpretar de una formasimplificada. Dado un número representado en base 2, su equivalente en decimal se obtiene sumando aquellas potencias de 2cuyo exponente corresponde al lugar en el que se encuentra el dígito 1.

Considérese el número en binario 1101011. Su equivalente en decimal se obtiene mediante la siguiente suma:1101011 = 26 +25 +23 +21 +20 = 64+32+8+2+1 = 107.

Por tanto, para manipular números codificados en base 2 y saber su equivalente en decimal es importante familiarizarse con losvalores de las potencias de 2 que se muestran el la Tabla 2.1

Bit 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15Peso 20 21 22 23 24 25 26 27 28 29 210 211 212 213 214 215

Decimal 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768

Tabla 2.1: Potencias de 2

La Tabla 2.2 muestra ejemplos de cómo obtener la representación en decimal de números en binario de ocho bits.

Peso 128 64 32 16 8 4 2 1 TotalBinario 0 0 1 0 0 1 1 1Decimal 32 4 2 1 39

Binario 1 0 1 1 0 0 1 0Decimal 128 32 16 2 178

Binario 1 1 0 1 1 0 0 1Decimal 128 64 16 8 1 217

Tabla 2.2: Conversión de binario a decimal

La conversión de un número en base 10 a binario se realiza siguiendo el procedimiento descrito en sección 2.2.1. En este caso, eldivisor es 2 y el resto sólo puede ser 0 o 1 produciendo los dígitos de la representación en base 2. Por ejemplo, la representaciónbinaria de 217 se obtiene tal y como muestra la ecuación 2.5

Page 33: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

33 / 198

217 = (108∗2)+1108 = (54∗2)+054 = (27∗2)+027 = (13∗2)+113 = (6∗2)+1

6 = (3∗2)+03 = (1∗2)+11 = (0∗2)+1

EQUATION 2.5: Traducción de base 10 a base 2

Los dígitos del número en base 2 se obtienen de menor a mayor peso, por tanto el resultado es 11011001 que corresponde con elcontenido de la Tabla 2.2.

La representación en base 2 tiene ciertas propiedades muy útiles para operar con estos números. Para saber si un número es par oimpar basta con mirar el bit de menos peso. Si dicho bit es uno, el número es impar, si es cero, el número es par. La demostraciónde esta propiedad es trivial. El equivalente en decimal de un número en binario se obtiene sumando potencias de 2. Todas estaspotencias, a excepción de la primera (20) son pares. Por tanto, un número impar debe tener un uno en su bit de menos peso. Deigual forma, todo número par debe tener un cero en su bit de menos peso, pues sólo puede constar de potencias de 2 pares.

La segunda propiedad no sólo aplica a la base 2, sino a cualquier base. Las operaciones de multiplicación y división entera porla base se realizan añadiendo un cero como dígito de menos peso o quitando el dígito de menos peso respectivamente.

Para los números en base 10, la operación de multiplicación por 10 se realiza añadiendo un cero como dígito de menos pesoal número dado. Por ejemplo: 1345 * 10 = 13450. De igual forma, si un número decimal lo dividimos por diez, el cociente seobtiene ignorando el dígito de menos peso, que a su vez corresponde con el resto de la división. Siguiendo con el mismo ejemplo,1345 dividido entre 10 produce un cociente de 134 y un resto de 5.

Volviendo a la representación binaria, en este caso, la multiplicación y división entera por 2 corresponden de forma análoga conlas operaciones de añadir un cero como dígito de menos peso o quitar el dígito de más peso. Por ejemplo, el número binario100111 que en decimal representa el 39, si se multiplica por 2 se obtiene 1001110 que se puede comprobar que representa el 78en decimal. Análogamente, si el mismo número se divide entre 2, su cociente es 10011 que representa el número 19, y el resto es1 (39 = 19 * 2 + 1).

2.4. Codificación en bases 8 y 16

La codificación en base 8 (también denominada codificación octal) a pesar de que aparentemente no es útil en el contexto de lalógica digital, cumple una propiedad especial que la hace importante. Aplicando los conceptos presentados en la sección 2.2 losnúmeros codificados en esta base constan de dígitos entre el 0 y el 7. Consecuentemente, tras el 7, el siguiente número es el 10,y tras el 77 el siguiente número es el 100.

Para traducir un número dado en base 10 a base 8 se procede mediante sucesivas operaciones de división entre 8 de las que seobtienen los dígitos correspondientes. En principio es posible realizar una traducción de un número en binario a un número enbase 8. Al menos se puede obtener la representación en base 10 del número binario, y luego efectuar su traducción a base 8. Pero,¿se puede realizar esta traducción directamente?

Analizando las operaciones necesarias para la traducción se descubre esta se puede hacer de forma inmediata. La división entre8 en números binarios corresponde a una división entre una potencia de la base, más concretamente 23. Tal y como se ha descritoen la sección 2.3, esta operación es equivalente a tres divisiones entre 2, o lo que es lo mismo, a eliminar los tres bits de menospeso del número que a su vez representan el resto de la división. Estos dos resultados son precisamente los que se necesitan paraefectuar la traducción.

Por tanto, para traducir un número directamente de binario a base 8 no hay más que agrupar los bits de tres en tres comenzandopor los de menor peso, y traducir cada grupo de 3 bits a un dígito entre 0 y 7. Con 3 dígitos binarios se pueden representarexactamente los números del 0 al 7 tal y como muestra la Tabla 2.3.

Page 34: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

34 / 198

Dígitooctal 0 1 2 3 4 5 6 7

Binario 000 001 010 011 100 101 110 111

Tabla 2.3: Correspondencia entre grupos de 3 bits y dígitos en octal

En el caso de que el último grupo no tenga 3 bits, los bits que faltan se consideran con valor cero (pues los ceros a la izquierdano alteran el valor de un número). La Tabla 2.4 muestra un ejemplo de cómo se realiza esta traducción.

Número en Binario Grupos de 3 bits Número en Octal001001112 000 = 0 100 = 4 111 = 7 478101100102 010 = 2 110 = 6 010 = 2 2628110110012 011 = 3 011 = 3 001 = 1 3318

Tabla 2.4: Traducción de binario a octal

Dado lo fácil que es traducir un número de binario a octal y viceversa, esta última base se utiliza como una representación máscompacta de los números binarios. En lugar de escribir un conjunto de unos y ceros, se escribe su equivalente en octal. Tancomún es esta representación que para denotar que un número está escrito en base 8, en lugar de añadir el subíndice tras el dígitode menos peso, se añade un cero a la izquierda. Por tanto, los números 478 y 047 representan ambos el número 47 en octal.

Este proceso de traducción tan inmediato se deriva de la propiedad de que la base 8 es una potencia de la base 2. Gracias a estapropiedad, las divisiones sucesivas y obtención del resto no es más que agrupar los bits comenzando por el de menos peso.

La base 8 no es la única que tiene esta propiedad. La siguiente base en orden creciente que es también potencia de dos es la base16. ¿Es posible escribir números en esta base? Siguiendo los conceptos presentados en la sección 2.2 se necesitan tantos dígitoscomo indica la base comenzando desde el cero. Además de utilizar los diez dígitos del 0 al 9 todavía hacen falta seis dígitosmás. La solución es utilizar las seis primeras letras del abecedario: A, B, C, D, E y F. Los 16 dígitos utilizados para representarnúmeros en base 16 son:

Aplicando las reglas descritas anteriormente, por ejemplo, al número F le sigue el 10, al 19 le sigue el 1A, al 1F le sigue el 20, al99 le sigue el 9A, y al 100 le precede el FF.

A esta codificación se le conoce también con el nombre de codificación hexadecimal. ¿Es posible hacer una traducción directa deun número en binario a un número en hexadecimal? La operación necesaria para obtener los dígitos es la división entre 16. Pero,al ser una potencia de 2 (24) la operación consiste en descartar los cuatro bits de menos peso del número binario, que a su vezcorresponden con el resto de la división. Por tanto, para obtener un número hexadecimal a partir de un número binario se han deagrupar los bits de cuatro en cuatro comenzando por los de menos peso. Cada uno de ellos se traduce en un dígito hexadecimal.Con 4 bits se codifican exactamente los 16 dígitos que utiliza la base 16 tal y como muestra la Tabla 2.5.

Dígito He-xadecimal 0 1 2 3 4 5 6 7

Binario 0000 0001 0010 0011 0100 0101 0110 0111Dígito He-xadecimal 8 9 A B C D E F

Binario 1000 1001 1010 1011 1100 1101 1110 1111

Tabla 2.5: Correspondencia entre grupos de 4 bits y dígitos en hexadecimal

Al igual que con la base 8, la base hexadecimal se utiliza como representación más compacta de los números en binario. Paraevitar la ambigüedad en la representación, un número en hexadecimal se representa añadiendo el prefijo ‘0x’ al comienzo delnúmero. La Tabla 2.6 muestra ejemplos de correspondencia entre la representación binaria y la hexadecimal.

La conversión de hexadecimal a base 10 se hace de forma idéntica al resto de las bases. Los dígitos de la A a la F tienen valornumérico del 10 al 15, y la base a utilizar es 16. Por ejemplo:

Page 35: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

35 / 198

Número en Binario Grupos de 4 bits Número en Hexadecimal001001112 0010 = 2 0111 = 7 0x27101100102 1011 = 11 0010 = 2 0xB2110110012 1101 = 13 1001 = 9 0xD9

Tabla 2.6: Traducción de binario a hexadecimal

0x27 = 2∗161 +7∗160 = 390xB2 = 11∗161 +2∗160 = 1780xD9 = 13∗161 +9∗160 = 217.

2.5. Tamaño de una codificación

En las secciones anteriores se ha visto cómo codificar números naturales en binario. La representación de un número correspondecon un conjunto de bits. Pero ¿cuántos bits son necesarios para representar los números naturales? Dado que hay infinitos núme-ros, la respuesta es infinitos bits. Pero para que un circuito digital sea capaz de manipular este tipo de números, su representacióndebe tener un tamaño finito.

Esta limitación se traduce en que, además de definir un esquema por el que se codifican los elementos necesarios utilizando elcódigo binario, también se debe fijar el tamaño de dicha codificación y lo que sucede cuando esta codificación no es suficiente.Por ejemplo, se decide representar los números naturales en binario con un tamaño de 10 bits. Sólo los números en el intervalo[0,210 - 1] pueden ser representados. El último número de dicho intervalo es el 1111111111 binario que corresponde con elnúmero 1023 en decimal.

El problema aparece si el procesador manipula los números naturales con 10 dígitos y se debe ejecutar la operación 1023 +1. El resultado es calculable, pero su representación con 10 bits no es posible. A esta situación, se obtiene un número cuyarepresentación no es posible, se le denomina overflow o ‘desbordamiento’. Los procesadores detectan y notifican esta situaciónpor tratarse de una anomalía en la codificación.

El número de bits utilizado para codificar los naturales es un parámetro que depende del procesador utilizado. Cuantos másdígitos se utilicen más números se pueden representar, pero a la vez más complicado es el diseño de la lógica interna encargadade realizar las operaciones. A lo largo de la historia, los procesadores han ido utilizando cada vez más bits para representar losnúmeros naturales, comenzando por 8 bits (que permiten codificar los números del 0 al 255) hasta los 128 bits de procesadoresmás avanzados.

El problema del tamaño de la codificación no es único para la representación de números naturales. Cualquier conjunto con unnúmero infinito de elementos a representar en binario tiene el mismo problema. Dependiendo del tamaño de la codificación, tansólo un subconjunto de sus elementos será representado y el procesador debe detectar y notificar cuando se requiere codificar unelemento cuya representación no es posible.

2.6. Codificación de números enteros

La codificación de números enteros en binario se puede realizar de diferentes formas. La más sencilla se conoce con el nombrede ‘signo y magnitud’. Esta codificación está basada en la observación de que todo número entero se puede considerar como unnúmero natural, su valor absoluto, y un signo positivo o negativo. Por ejemplo, el número -345 se puede representar como el par(-, 345). El valor absoluto de un entero, por definición es un número natural, y por tanto se puede utilizar la codificación binariadescrita en la sección 2.3. Respecto al signo, dado que tiene dos posibles valores, su codificación en binario es trivial, con unúnico bit en el que el valor 0 representa el signo positivo y el valor 1 el signo negativo.

La traducción de un entero en base 10 a su representación en binario en signo y magnitud es directa: se codifica el valor absolutocomo un número natural y el signo utilizando un bit adicional. El bit de signo se escribe como bit de más peso. La Tabla 2.7muestra ejemplos de la codificación en signo y magnitud.

Page 36: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

36 / 198

Número en decimal Signo Valor absoluto Signo y magnitud-342 - = 1 342 = 101010110 1101010110342 + = 0 342 = 101010110 0101010110-23 - = 1 23 = 10111 110111

Tabla 2.7: Ejemplo de codificación de enteros en signo y magnitud

Si se utiliza una codificación de números enteros mediante signo y magnitud de n bits, se representan los enteros en el intervalo[-2n-1-1,2n-1-1]. Esta expresión se deriva de que el mayor número posible es aquel que comienza por un cero seguido de unos yque corresponde precisamente con el valor 2n-1-1. Análogamente, el menor número representado es el que tiene todos los dígitosa 1 y corresponde con el anterior límite, pero negativo. La figura 2.1 ilustra este rango para una representación con 8 bits sobrela recta que de números enteros.

Figura 2.1: Rango de enteros codificados por 8 bits en signo y magnitud

Pero esta técnica de codificación tiene una propiedad no deseada. Con n bits se pueden representar 2n símbolos, pero si se realizanlas operaciones, con la codificación de signo y magnitud, se representan 2n - 1. El problema reside en la codificación del númerocero, pues es un número que no tiene signo, y por tanto la representación formada por sólo ceros y la formada por ceros con ununo a la izquierda son equivalentes.

Esto quiere decir que un elemento se representa por dos combinaciones de bits, con lo que se está desperdiciando la codificaciónde un número adicional. Exista una codificación alternativa a signo y magnitud que no tiene esta anomalía y se denomina‘complemento a dos’.

La codificación en complemento permite codificar 2n números enteros consecutivos utilizando n bits. Más concretamente, elrango de enteros representado por n bits es [-(2n-1), 2n-1 - 1]. La figura 2.2 muestra un ejemplo de codificación de enteros encomplemento a 2 con 8 bits. El código con ocho unos representa el número -1.

Figura 2.2: Rango de enteros codificados por 8 bits en complemento a 2

Esta codificación tiene múltiples propiedades que la hacen muy eficiente. El problema de la doble codificación para el númerocero presente en la codificación con signo y magnitud no está presente en complemento a dos. El cero tiene una única represen-tación y corresponde con su valor en base 2. El bit de la izquierda o más significativo sigue representando el signo del númerocon idéntica codificación que en el caso de signo y magnitud, los números positivos tienen este bit a cero y los negativos a uno.Los números positivos se codifican de forma idéntica a los números naturales, es decir, con su codificación en base 2.

Pero la propiedad más interesante de esta codificación es que las operaciones de suma y resta de números en complemento a dossiguen exactamente las mismas reglas que los números codificados en binario. Esta propiedad tiene una importancia enorme enel contexto de los circuitos digitales puesto que si se implementa un circuito que calcula la suma y resta de números naturales,dicho circuito se puede utilizar sin modificación alguna para sumar y restar enteros representados en complemento a 2.

La traducción de un número entero en base 10 a su representación con n bits en complemento a 2 se realiza mediante las siguientesreglas:

Page 37: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

37 / 198

Si el número mayor o igual que cero, su representación corresponde es directamente su traducción a base 2 con n bits.

Si el número es negativo, su representación se obtiene mediante tres operaciones:

a. Obtener la representación del valor absoluto del número.b. Reemplazar cada cero por un uno y cada uno por un cero. A esta operación también se le conoce como ‘negar’ el número.c. Sumar el valor 1 al número obtenido.

Por ejemplo, para calcular la representación del número -115 en complemento a dos con 8 bits, primero se calcula la repre-sentación en base dos con ocho bits del su valor absoluto 115, que es 01110011 (o su equivalente en hexadecimal 0x73). Acontinuación se niega el número y se obtiene 10001100. Finalmente, se suma 1 al número y se obtiene 10001101.

La traducción de un número N en complemento a dos con n bits a su representación en base 10 se realiza mediante las siguientesreglas:

Si el número N es positivo, es decir, el bit de más peso es cero, el número en base 10 se obtiene igual que en el caso de losnúmeros naturales.

Si el número N es negativo, es decir, el bit de más peso es uno, el número en base 10 se obtiene mediante la fórmulaABS(N)− (2n)

donde ABS(N) representa el número en base 10 que se obtiene al interpretar los bits en N como un número natural.

Por ejemplo, considérese el cálculo del valor en base 10 del número en complemento a dos de ocho bits 10110110. Como el bitde más peso es 1, el número es negativo. Su valor en base 10 es, por tanto

ABS(10110110)− (2n) = ABS(10110110)−256= 182−256= −74

La Tabla 2.8 muestra la equivalencia entre las representaciones en base dos y en decimal de los números naturales y los enterosen complemento a dos.

Números Representación en base 10N ∈ [0,2n−1] N = ∑

n−10 2ibi

Enteros positivos.N ∈ [0,2n−1−1]

N empieza por ceroN = ∑

n−10 2ibi

Enteros negativos.N ∈ [−2n−1,−1]

N empieza por uno.

N = ABS(N)−2n

=n−1

∑0

2ibi−2n

Tabla 2.8: Representación de números naturales y enteros en binario con n bits

Si se precisa cambiar el número de bits con el que representar un número en complemento a dos, la operación no es idéntica alcaso de los números naturales. Un número natural en binario no cambia si se le añaden ceros a la izquierda. Los enteros positivosrepresentados en complemento a dos conservan esta regla. Sin embargo, la extensión de un número negativo representado encomplemento requiere una operación diferente.

Los números negativos en complemento a 2 tiene su bit más significativo a uno, por tanto, para aumentar el número de bits no sepueden añadir ceros. En complemento a dos, todo número negativo mantiene su valor si se le añaden unos a la izquierda del bitde más peso. En otras palabras, para extender la representación de un número en complemento a dos basta con extender el valorque tenga como bit más significativo. A esta operación se le conoce con el nombre de ‘extensión de signo’.

Page 38: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

38 / 198

2.7. Codificación de números reales

La codificación de números reales utilizando lógica binaria es significativamente más compleja que el caso de los naturales oenteros. Parte de esta complejidad deriva del hecho de que si bien al utilizar un número finito de bits se representaba un intervaloconcreto de números enteros o naturales, en el caso de los números reales esta técnica no es posible.

Dado que entre dos números reales existe un número infinito de números, no es posible representar todos los números en unintervalo concreto sino que se representan únicamente un subconjunto de los números contenidos en dicho intervalo. Esta pro-piedad plantea un inconveniente que debe ser tenido en cuenta no sólo en el diseño de los circuitos digitales capaces de procesarnúmeros reales, sino incluso en los programas que utilizan este tipo de números.

Supóngase que se operan dos números reales representados de forma binaria y que el resultado no corresponde con uno delos números que pueden ser representados. Esta situación es perfectamente posible dado que entre dos números hay infinitosnúmeros reales. La única solución posible en lógica digital consiste en representar este resultado por el número real más próximoen la codificación. La consecuencia inmediata es que se ha introducido un error en la representación de este resultado. Engeneral, cualquier número real fruto de una operación tiene potencialmente el mismo problema. En algunos casos este error noexiste porque el número sí puede ser representado de forma digital, pero en general, la manipulación de números reales puedeintroducir un error.

Este posible error introducido por la representación adquiere especial relevancia en aquellos programas que realizan cálculosmasivos con números reales. Existen técnicas de programación orientadas a minimizar el error producido cuando se manipulannúmeros.

Los números reales se codifican en lógica binaria mediante la técnica conocida como ‘mantisa y exponente’ que está basada en lasiguiente observación: todo número real consta de una parte entera y una parte decimal. La parte entera es aquella a la izquierdade la coma, y la parte decimal a la derecha. A esta parte decimal se le denomina ‘mantisa’. En el contexto de los números reales,la multiplicación y división por potencias de la base es equivalente al desplazamiento de la coma a lo largo de los diferentesdígitos que conforman el número. Una multiplicación por una potencia positiva de la base implica un desplazamiento de la comaa la derecha, y de forma análoga, la multiplicación por una potencia negativa de la base es equivalente a un desplazamiento de lacoma a la izquierda. El ejemplo 2.2 muestra esta equivalencia para los números reales en base 10.

Ejemplo 2.2 Multiplicación de números reales por potencias de la base

14345.342 = 1434.5342∗10= 143.45342∗102

= 14.345342∗103

= 1.4345342∗104

= 0.14345342∗105

Mediante operaciones de multiplicación y división por la base es posible representar todo número real por una mantisa en laque el primer dígito significativo está a la derecha de la coma multiplicado por una cierta potencia de la base. La ventaja de larepresentación en coma flotante respecto a la representación en coma fija es que permite representar números muy pequeños omuy grandes de forma muy compacta. El número 0.1*10-10 necesita 11 dígitos para representarse en punto fijo, sin embargo, encoma flotante utilizando base 10 tan sólo se precisa representar la mantisa 0.1 y el exponente -10.

La representación de los números reales positivos en base 2 sigue las mismas reglas que la representación de los naturales en loque respecta al peso de cada uno de sus dígitos. El peso de los bits de la parte decimal se obtiene multiplicando por 2 elevado asu posición pero con exponente negativo. Por ejemplo:

101.111 = 22 +20 +2−1 +2−2 +2−3

= 4+1+12

+14

+18

= 5.875

La notación de mantisa y exponente se puede aplicar de forma análoga a números codificados en base 2. En este caso las potenciasutilizadas en la multiplicación son potencias de 2. El ejemplo 2.3 muestra esta equivalencia en la representación binaria.

Page 39: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

39 / 198

Ejemplo 2.3 Multiplicación por potencias de 2 en números reales binarios

101.111 = 10.1111∗21

= 1.01111∗22

= 0.101111∗23

Los números reales, por tanto, se representan tal que su primera cifra significativa en la mantisa sea aquella que está a la derechade la coma y se multiplica por la potencia pertinente de la base. La codificación de los números reales en base 2 consta de trespartes: la mantisa, su signo y el exponente. La base sobre la que se aplica el exponente está implícita en la representación, y es labase 2.

El bit de signo hace referencia al signo de la mantisa y se mantiene la misma convención que en el caso de la codificación deenteros como signo y magnitud (ver sección 2.6), el signo positivo se representa como 0 y el negativo como 1.

La mantisa representa la parte decimal del número y tiene una influencia directa sobre su precisión. Cuantos más bits se incluyanen la mantisa, mayor precisión tendrá la codificación. Tiene sentido hablar de ‘precisión’ de la representación porque se estáconsiderando un subconjunto de todos los números reales posibles.

Para la mantisa se aplica una mejora que permite el incremento de la precisión. Como esta se obtiene desplazando el númerohasta que el primer dígito significativo esté a la derecha de la coma, en base 2, esto quiere decir que dicho dígito siempre es ununo y por tanto no es preciso almacenarlo. Por tanto, si una representación de números reales utiliza 23 bits para la mantisa, enrealidad está representando 24 bits, pues el primero es siempre 1. A esta técnica se le conoce con el nombre de ‘bit escondido’.

El exponente es un número entero y por tanto se puede utilizar cualquiera de las técnicas de codificación presentadas anterior-mente. La más común es complemento a 2. La figura 2.3 muestra la estructura de la representación binaria de un número real encoma flotante.

Figura 2.3: Estructura de la representación binaria en coma flotante

En este tipo de codificación no basta con saber el tamaño en bits de su representación, sino que es preciso especificar además,cuántos bits se utilizan para codificar la mantisa y el exponente (el signo siempre se codifica con un bit).

2.7.1. Desbordamiento en la representación en coma flotante

Al igual que en el caso de los números naturales y enteros, cuando un número está fuera del rango de representación, se produce unde desbordamiento, pero en el caso de los números reales, esta situación es más compleja. Aparte del problema de representaciónde números mayores al rango posible, también aparece un problema cuando el valor absoluto de un número es demasiadopequeño.

Por ejemplo, supóngase que el valor más pequeño diferente de cero que se puede representar mediante coma flotante es n. Aldividir dicho número por 3, la representación debe escoger el número real más próximo que pueda ser representado, que en estecaso es el cero.

Pero que un número diferente de cero se represente como cero tiene efectos muy significativos en los cálculos. Por ejemplo, si elnúmero que ha producido el resultado cero se multiplica por cualquier otro factor, el resultado es cero, y por tanto incorrecto. Enrealidad, la propiedad que hace esta situación tan delicada es que, en adelante, no hay forma de acotar el error producido por larepresentación en coma flotante. A esta situación se le conoce con el nombre de ‘desbordamiento por abajo’ o underflow.

Las situaciones de desbordamiento al operar números en coma flotante suelen producir excepciones en la ejecución de un pro-grama que pueden ser procesadas por los propios programas para recuperarse, o bien producen la terminación abrupta de suejecución.

Page 40: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

40 / 198

2.7.2. El estándar IEEE 754

La representación de números reales en coma flotante puede seguir diferentes estrategias dependiendo del número de bits paracodificar mantisa y exponente, tipo de codificación del exponente, cómo se tratan condiciones especiales como desbordamiento,etc.

El Instituto de Ingeniería Eléctrica y Electrónica (en adelante IEEE) ha propuesto dos estándares para la representación de nú-meros reales, el IEEE 754 y el IEEE 854, de los cuales, el más utilizado es el IEEE 754. Esta representación tiene cuatro posiblesprecisiones: precisión simple, simple extendida, precisión doble, y doble extendida. La Tabla 2.9 muestra las características decada una de ellas. Nótese que en algunos de los parámetros, el estándar tan sólo especifica una cota, y no un valor fijo.

Parámetro Simple Simple Extendida Doble Doble Extendidabits de la mantisa 24 32 53 64máximo exponente 127 1023 1023 ≥16383mínimo exponente -126 ≤-1022 1022 ≤16382bits del exponente 8 ≤11 11 15tamaño total 32 43 64 79

Tabla 2.9: Parámetros del formato IEEE 754

La mantisa se representa utilizando la codificación de signo y magnitud y aplicando la técnica de bit escondido. Por ejemplo, enla precisión simple se utiliza un bit para el signo y 24 para la magnitud. En el bit de signo el 0 representa el signo positivo y el 1el negativo.

Los exponentes son números enteros su valor se representa utilizando un esquema de desplazamiento o suma de una constante quepara la precisión simple es 127 y para la doble es 1023. El valor real del exponente se obtiene restando la constante pertinente desu interpretación en base 2. Por ejemplo, en la precisión simple del formato, si el exponente contiene el número 23, correspondecon el exponente 23 - 127 = -104 y en precisión doble con 23 - 1023 = -1000. Los exponentes con valores todo ceros o todo unosestán reservados para situaciones excepcionales.

Los rangos resultantes de estas representaciones difieren significativamente de los obtenidos en las representaciones de enteros ynaturales. A igual número de bits, la representación en coma flotante cubre un rango más extenso de números pero a condición derepresentar sólo un subconjunto de ellos. La Tabla 2.10 muestra los rangos de representación de las precisiones simple y doble.

Precisión Negativos Positivos

Simple [−(2−2−23)∗2127,−(2−126)] [2−126,(2−2−23)∗2127]

Doble [−(2−2−52)∗21023,−(2−1022)] [2−1022,(2−2−52)∗21023]

Tabla 2.10: Rangos representados en los formatos simple y doble

Para el caso concreto de la precisión simple, hay cinco rangos numéricos que son imposibles de representar.

1. Números negativos menores que -(2-2-23)*2127. Producen un desbordamiento negativo.

2. Números negativos mayores que -2-126. Producen un desbordamiento por abajo.

3. El número cero

4. Números positivos menores que 2-126. Producen un desbordamiento por abajo.

5. Números positivos mayores que (2-2-23)*2127. Producen un desbordamiento positivo.

El número cero no puede ser representado con este esquema debido a la utilización de la técnica del bit escondido. Para solventareste problema se le asigna un código especial en el que tanto la mantisa como el exponente tienen todos sus bits a cero y el bit designo es indeterminado (con lo que el cero tiene dos posibles representaciones).

Page 41: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

41 / 198

Otros dos valores a los que se les asigna un código especial son +∞ y -∞ que se codifican con el pertinente bit de signo, elexponente con todo unos y la mantisa con todo ceros.

Otro caso especial a considerar con esta codificación es cuando se produce un resultado que es imposible de representar. Paraesta situación se utiliza la notación ‘NaN’ (acrónimo de Not a Number). Estos valores a su vez se dividen en dos categoríasdependiendo si el resultado es indeterminado o inválido y se denotan respectivamente por los símbolos ‘QNaN’ y ‘SNaN’. Enambos casos el exponente tiene todos sus bits a uno y la mantisa es diferente de cero. El valor de la mantisa se utiliza paradistinguir entre las dos posibles situaciones.

2.8. Representación de conjuntos de símbolos

Aparte de manipular números, un procesador debe poder representar y manipular conjuntos arbitrarios de símbolos. Al igual queen el caso de los números, la lógica digital fuerza a que dichos símbolos se codifiquen con bits pero, a diferencia de los números,un conjunto de símbolos arbitrario no tiene un conjunto de operaciones específicas que se realizan sobre él.

La definición de una codificación de un conjunto de símbolos precisa tres datos:

el conjunto de símbolos,

el número de bits a utilizar en la codificación,

la correspondencia entre cada símbolo del conjunto y la secuencia de bits que lo representa.

El número de bits a utilizar tiene la restricción derivada de la ecuación 2.1. Con n bits se pueden codificar un máximo de 2n

elementos, por tanto, si se denota por C la cardinalidad del conjunto de símbolos se debe cumplir la ecuación 2.6.

C ≤ 2n

EQUATION 2.6: Relación entre la cardinalidad del conjunto y el número de bits

Por ejemplo, se dispone del conjunto de símbolos para codificar S = { Rojo, Verde, Azul }. Se decide utilizar el mínimo númerode bits para su codificación, en este caso 2. La correspondencia entre los símbolos y su codificación se establece mediante lasiguiente tabla

Símbolo CodificaciónRojo 00Verde 01Azul 10

Como la cardinalidad del conjunto no es una potencia de dos, existen más combinaciones de bits que elementos lo que permiteque existan múltiples posibles correspondencias.

2.8.1. Codificación de caracteres

Uno de los conjuntos de símbolos que más se utilizan en un procesador son aquellos que se introducen a través del teclado. Desdela aparición de los primeros procesadores ha existido la necesidad de tener una codificación para estos símbolos. Además, dadoque los ordenadores intercambian entre sí infinidad de datos, esta codificación es deseable que sea idéntica para todos ellos.

Una de las codificaciones de letras que más trascendencia ha tenido en los últimos años es la codificación ASCII (AmericanStandard Code for Information Interchange). En ella se incluyen so sólo letras y dígitos, sino también códigos especiales parala transmisión de mensajes a través de teletipos. El tamaño de la representación es de 8 bits y por tanto, el número máximo desímbolos que puede codificar es 256

El código contiene en sus primeras 32 combinaciones (de la 00000000 a la 0100000) un conjunto de símbolos que no sonimprimibles y que se utilizaban para la transmisión de texto entre dispositivos. Los símbolos con códigos del 33 al 127 sonlos que sí pueden imprimirse. Por ejemplo, el espacio en blanco se codifica como 0x20. Las letras del la ‘a’ a la ‘z’ ocupan

Page 42: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

42 / 198

los códigos del 0x61 al 0x7A (en este rango no está incluida la ñ). Sus correspondientes símbolos en mayúsculas ocupan loscódigos del 0x41 al 0x5A (la diferencia numérica entre los códigos de mayúscula y minúscula es idéntica).

Pero el código ASCII no fue el único utilizado para representar letras, sino que ha convivido con otras alternativas similares talescomo EBCDIC (Extended Binary Coded Decimal Interchange Code) que aun se utilizan en algunos de los ordenadores actuales.

Una de las carencias más importantes del código ASCII es la ausencia de codificación para los símbolos que no son parte delalfabeto anglosajón, como por ejemplo, todas las letras que incluyen tildes, diéresis, etc. Para dar cabida a estos símbolos sedefinió lo que se conoce como el código ASCII extendido que incluye en los valores del 128 al 255 estos símbolos así como unconjunto de símbolos gráficos y matemáticos.

Esta extensión, a pesar de dar cabida a algunos de los alfabetos utilizados en países de habla no inglesa, no fue suficiente paraincorporar alfabetos tales como los asiáticos o los de oriente medio que constan de un número muy elevado de grafías.

La única solución posible ha sido proponer una nueva codificación con el tamaño suficiente para dar cabida a todos los alfabetosexistentes. Con tal motivación se diseño la codificación ‘Unicode’ cuyo objetivo es proveer una única representación numéricapara cada símbolo independientemente de la plataforma, el programa o el lenguaje en el que se manipule.

La codificación Unicode se ha transformado en un estándar adoptado por las principales empresas de hardware y software. Supresencia no cubre la totalidad de aplicaciones, pero con el paso del tiempo será la única representación utilizada.

El estándar pretende ser lo más genérico posible, y por tanto, en lugar de fijar un único tamaño para la representación, sucodificación la divide en tres posibles formas: 8 bits, 16 bits y 32 bits. Estas codificaciones son diferentes pero todas son partedel estándar y se conocen con los nombres de ‘UTF-8’, ‘UTF-16’ y ‘UTF-32’ respectivamente. La correspondencia entre larepresentación numérica y los símbolos está perfectamente definida y tabulada en cada una de los tres formatos. La Tabla 2.11muestra un ejemplo de tres símbolos y su codificación en Unicode.

Imagen Símbolo Códigoz z minúscula 0x007A

agua en chino 0x6C34

clave de sol 0xD8340xDD1E

Tabla 2.11: Ejemplo de símbolos codificados con Unicode

Una vez definida la codificación de todas las letras y símbolos adicionales, las cadenas de estos símbolos se representan medianteuna secuencia de estos códigos en los que cada número corresponde con una letra. Esta codificación es la utilizada por los editoresde texto plano para la representación interna del texto. Algunos de ellos incluso permiten cambiar la codificación utilizadaentre ASCII y alguno de los formatos Unicode. La Tabla 2.12 muestra el texto de un programa en lenguaje ensamblador y surepresentación equivalente utilizando el código ASCII (los valores numéricos están en hexadecimal).

2.8.2. Codificación de instrucciones

Una de las codificaciones más importante que necesita un procesador es el de su propio conjunto de instrucciones. En él, cadaposible instrucción con sus operandos se considera un elemento. Para su codificación es preciso escoger tanto el número de bitscomo la correspondencia entre instrucciones y su codificación binaria.

Para ilustrar este tipo de codificación se utilizará un conjunto inicial de instrucciones sencillas a modo de ejemplo en el quese irán incorporando de forma gradual más elementos para ver cómo la codificación puede ser adaptada. El conjunto inicial deinstrucciones se denota por el nombre ‘ual-1’.

En lugar de definir el conjunto de instrucciones mediante una simple enumeración de todos sus elementos, se divide la instrucciónen partes y se proponen codificaciones separadas para los valores de cada una de las partes. Las instrucciones del conjunto ual-1constan de tres partes: una operación y dos operandos que son dos números reales en el rango 0 a 255. El código de operación

Page 43: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

43 / 198

Texto

.datamsg: .asciz "Hello world\n"

.text

.globl mainmain: push $msg

call printfadd 4, %esp

ret

Codificación ASCII

20 20 20 20 20 20 2E 64 61 74 61 0A6D 73 67 3A 20 20 2E 61 73 63 69 7A 20 22 ←↩

48 65 6C 6C...20 20 20 20 20 20 2E 74 65 78 74 0A20 20 20 20 20 20 2E 67 6C 6F 62 6C 20 73 ←↩

74 61 72 74...6D 61 69 6E 3A 20 70 75 73 68 20 24 6D 73 ←↩

67 0A20 20 20 20 20 20 63 61 6C 6C 20 70 72 69 ←↩

6E 74 66 0A20 20 20 20 20 20 61 64 64 20 24 34 2C 20 ←↩

25 65 73 70....20 20 20 20 20 20 72 65 74 0A

Tabla 2.12: Texto de un programa y su codificación en ASCII

puede tener uno de los siguientes cuatro valores: add, sub, mul y div. La figura 2.4 muestra la estructura de las instruccionesque conforman este conjunto de símbolos así como varias instrucciones de ejemplo.

Figura 2.4: Estructura de las instrucciones de ual-1

El primer paso para diseñar una codificación es calcular el número de elementos que contiene ual-1. La primera parte tiene 22

posibles valores, la segunda 28 y la tercera igualmente 28 posibles valores. Todas las combinaciones son posibles, por tanto elnúmero de elementos se obtiene multiplicando estos factores:

22 ∗28 ∗28 = 218 = 262144

El número de bits y la cardinalidad deben satisfacer la ecuación 2.6 y por tanto se precisan al menos 18 bits. En lugar de utilizarel número mínimo de bits, se decide utilizar el menor múltiplo de 8 bits, es decir, 24 bits (3 bytes).

La correspondencia entre los símbolos y su representación en binario se establece igualmente de forma implícita para evitar laenumeración de todos los elementos. Las reglas de esta codificación son:

El código de operación se codifica con dos bits y la siguiente correspondencia:

Símbolo Codificaciónadd 00sub 01mul 10div 11

El segundo y tercer operandos se codifican con su representación en base 2.

Toda codificación se escribe de izquierda a derecha, y se completa con 6 dígitos consecutivos con valor 0 para obtener un totalde 24 bits.

La figura 2.5 ilustra el formato de la codificación binaria de los elementos de ual-1.

Figura 2.5: Formato de codificación del conjunto ual-1

Siguiendo esta codificación, la instrucción que representa la suma de los números 0x27 y 0xB2, representada por ADD 0x-27 0xB2, se codifica en binario tal y como se ilustra en la figura 2.6. La secuencia de 24 bits resultante se codifica en basehexadecimal para reducir su tamaño y facilitar su manipulación.

Page 44: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

44 / 198

Figura 2.6: Ejemplo de codificación de instrucción

La propiedad más importante de esta codificación es que la traducción de cualquier instrucción a su representación en binario yviceversa es un proceso sistemático.. La Tabla 2.13 muestra la codificación de otros símbolos del conjunto ual-1.

Símbolo CodificaciónADD 0x27 0xB2 0x09EC80SUB 0x11 0x2F 0x444BC0

MUL 0xFA 0x2B 0xBE8AC0DIV 0x10 0x02 0xC40080

Tabla 2.13: Representación en hexadecimal de símbolos de ual-1

En general, el número hexadecimal resultante no contiene los mismos dígitos que en el símbolo del que procede. Esto sucedeporque los bits son reorganizados e interpretados de forma diferente, pero la información sigue estando contenida en el resultado.

A continuación se define un nuevo conjunto de símbolos derivado de ual-1 pero con una estructura más compleja. Se añade acada símbolo un cuarto elemento que define el lugar donde almacenar el resultado de la operación y que puede tener los valoresLugarA o LugarB. Este nuevo conjunto se denotará por ual-2. La estructura de los símbolos de ual-2 así como ejemplos dealgunos de sus símbolos se muestra en la figura 2.7.

Figura 2.7: Estructura de las instrucciones de ual-2

Tras definir el nuevo conjunto, se obtiene el número de elementos de los que consta. De cada elemento del conjunto ual-1 seobtienen dos elementos del nuevo conjunto ual-2: uno con el sufijo LugarA y otro con el sufijo LugarB. Por tanto, el número deelementos de ual-2 es 219 y se requieren al menos 19 bits para su codificación. Al igual que en el caso de ual-1, la representaciónse realiza en múltiplos de bytes, y por tanto se utilizarán 24 bits.

La correspondencia entre los elementos de ual-2 y su representación binaria sigue las mismas reglas que para el caso de ual-1con la modificación de que el operando añadido se codifica con un único bit y según la codificación que se muestra en la Tabla2.14.

Símbolo CodificaciónLugarA 0LugarB 1

Tabla 2.14: Codificación del operando lugar

La nueva codificación utiliza 19 bits en lugar de los 18 anteriores y con la estructura que se ilustra en la figura 2.8.

Page 45: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

45 / 198

Figura 2.8: Estructura de la correspondencia de ual-2

El proceso de traducción de símbolo a su representación con seis dígitos hexadecimales y viceversa se puede hacer igualmentede forma sistemática. La Tabla 2.15 muestra varios ejemplos de representación de símbolos de ual-2 en binario y hexadecimal.

Símbolo Binario Hexadecimaldiv 0x10 0x02

LugarA11 0001 0000 0000

0010 0 000000xC40080

add 0x10 0x02LugarB

00 0001 0000 00000010 1 00000

0x0400A0

mul 0x10 0x02LugarA

10 0001 0000 00000010 0 00000

0x840080

Tabla 2.15: Representación en binario y hexadecimal de símbolos de ual-2

Al proceso de traducción de un símbolo del conjunto ual-2 a su equivalente en binario (o hexadecimal) se denominará ‘codifica-ción’, y al proceso inverso por el que se obtiene un símbolo a partir de su codificación en binario se denominará ‘decodificación’.Dadas la reglas de traducción, estos dos procesos se pueden realizar de forma automática.

La decodificación de instrucciones es precisamente lo que realiza un procesador cuando recibe una instrucción a ejecutar. Al igualque el resto de datos que manipula, las instrucciones están codificadas como secuencias binarias. Una vez recibida se decodificapara saber qué cálculo se debe realizar.

Los dos esquemas de codificación de los conjuntos ual-1 y ual-2 tienen múltiples decisiones arbitraras: la correspondencia delas operaciones con sus códigos de dos bits, el orden en el que se concatenan los códigos binarios, el número total de bits autilizar en la representación (mientras se respete el mínimo), la colocación de los bits de relleno, etc. Estas decisiones pueden sermodificadas dando lugar a codificaciones diferentes pero igualmente válidas. La propiedad que se debe mantener es la posibilidadde codificar y decodificar los símbolos de forma inequívoca.

Los bits de relleno añadidos a la derecha para alcanzar el tamaño de 24 bits ofrecen cierto grado de ambigüedad. Dados dosnúmeros binarios de 24 dígitos, si la única diferencia entre ellos radica en los bits de rellenos, al interpretarse como símbolosde ual-1 o ual-2, ambos corresponden con el mismo símbolo. Esta propiedad no cambia en nada el proceso de codificación ydecodificación, tan sólo pone de relieve el hecho de que el número de bits utilizado permite más combinaciones que número deelementos hay en el conjunto.

A continuación se define un nuevo conjunto, que se denotará por ‘ual-3’ y en el que en los dos primeros operandos que hastaahora sólo podía haber un número de ocho bits, ahora se permite o un número de ocho bits, o un lugar con valores LugarA oLugarB. Este nuevo conjunto extiende al conjunto ual-2 con aquellos símbolos en los que la segunda o tercera parte representaun lugar. Se puede comprobar que ual-2 es un subconjunto de ual-3.

Este nuevo conjunto representa aquellas instrucciones cuyos operandos no sólo son valores numéricos sino que pueden conteneruno de los dos posibles lugares LugarA o LugarB no sólo para almacenar el resultado (como indica el último campo de lainstrucción) sino como lugar de donde obtener un operando. Por ejemplo, el símbolo ADD LugarA 0x10 LugarB formaparte del nuevo conjunto ual-3 y podría representar la orden por la cual se obtiene el contenido de LugarA, se suma 0x10 y elresultado se almacena en LugarB.

La cardinalidad de este nuevo conjunto se calcula multiplicando el número de combinaciones posibles que tiene cada una de laspartes de la instrucción. El código de operación sigue teniendo cuatro posibles valores, pero ahora cada uno de los operandostiene los 256 posibles valores del número natural más dos posibles valores que representan un lugar. Por tanto el número deelementos de ual-3 es:

Page 46: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

46 / 198

22 ∗ (28 +2)∗ (28 +2)∗2 = 532512≤ 224

Siguiendo la política utilizada hasta ahora, el tamaño de la codificación se realiza en múltiplos de bytes, y por tanto, ocupa 24 bitsque siguen siendo suficientes. La correspondencia entre símbolos y su codificación binaria necesita ser revisada, pues ahora losvalores posibles de los operandos superan los 256 que se codificaban con ocho bits. Se precisa un esquema que permita codificarlos 258 posibles valores de cada uno de los operandos y para ellos se precisan al menos 9 bits, puesto que 258 > 28.

La codificación con 9 bits ofrece 512 combinaciones, mientras que tan sólo existen 258 posibles valores a codificar. Una posiblesolución consiste en dividir los 9 bits en dos grupos de 1 y 8 bits. Si el primer bit es cero indica que en los siguientes 8 se codificaun número natural entre 0 y 255. Si es uno indica que se codifica uno de los dos valores LugarA o LugarB. En el primer casose utilizan todos los bits, mientras que en el segundo, el lugar se codifica en el último de los ocho bits ignorando el valor de los 7bits restantes. La figura 2.9 ilustra este esquema de codificación.

Figura 2.9: Codificación de los operandos en ual-3

Al haber menos elementos (258) que codificaciones posibles con 9 bits (512), aparecen numerosas combinaciones que codificanel mismo operando. Concretamente, cuando se codifica un lugar, aquellas combinaciones con un uno en el primer bit, un de-terminado valor en el último y cualquier combinación en los siete bits restantes representan el mismo operando. La Tabla 2.16muestra ejemplos de la codificación de operandos en ual-3.

Codificación binaria Operando000010010 0x12100010011 LugarB001111010 0x7A100010010 LugarA1XXXXXXX0 LugarA

Tabla 2.16: Ejemplos de codificación de operandos en ual-3

Tal y como se muestra en la última fila de la Tabla 2.16, cuando el valor de un bit en una secuencia no es relevante, se suelerepresentar por el valor ‘X’.

Al aplicar la nueva correspondencia, el código binario resultante consta de siete partes: la operación, el bit que indica el tipo deprimer operando, el primer operando, el bit de tipo del segundo operando, el segundo operando, el tercer operando y los bits derelleno. La figura 2.10 muestra esta estructura.

Page 47: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

47 / 198

Figura 2.10: Formato de la codificación de ual-3

La Tabla 2.17 muestra ejemplos de codificación de instrucciones del conjunto ual-3.

Instrucción Binarioadd 0x01 0x00 LugarA 0x002000add 0x02 0x00 LugarB 0x004008mul LugarB 0x03 LugarA 0xA02030mul LugarB 0x04 LugarA 0xA02040

Tabla 2.17: Codificación de instrucciones de ual-3

Los esquemas de codificación como el mostrado hasta ahora son una simplificación de los utilizados para que un procesadorsepa qué instrucción debe ejecutar. Desde que el procesador recibe el voltaje necesario para funcionar, hasta que dicho voltajedesaparece, la única tarea que se realiza es la obtención de un conjunto de bits, su interpretación, la ejecución de la instrucciónpertinente y la obtención del siguiente conjunto de bits.

La codificación de una secuencia de instrucciones se transforma en una secuencia de códigos binarios, cada uno de los cualescodifica una instrucción y que el procesador carga una tras otra y las ejecuta. El lugar donde deben están almacenados estosvalores es la memoria RAM que se comparte con el almacenamiento de los datos.

El número de bits utilizado para codificar un conjunto de símbolos influye directamente en la cantidad de memoria necesaria paraalmacenar una secuencia de instrucciones. Cuanto más compacta sea la representación menor cantidad de memoria se utiliza ymás cantidad de información se puede almacenar, por lo que este es un criterio que se tiene en cuenta a la hora de diseñar lacodificación del lenguaje de un procesador.

A la vista del esquema de codificación utilizado para ual-3 cabe preguntarse: ¿es posible codificar las instrucciones utilizando unnúmero menor de bits para utilizar menos cantidad de memoria? En un primer análisis se puede comprobar que si la instruccióntiene como sus dos primeros operandos dos números de 8 bits, la codificación no puede ser reducida, pues cada uno de los bitstiene un cometido.

Sin embargo, en el caso de que alguno de los dos primeros operandos contenga un lugar, parte de los bits no se utilizan, por loque se puede considerar un esquema de representación más compacto. Se propone un nuevo esquema en el que la codificacióndel primer y segundo operando se modifica de la siguiente forma:

Si el operando es un número de ocho bits se mantiene la codificación anterior con un bit de prefijo con valor 0.

Si el operando es un lugar, se codifica con dos bits, el primero tiene valor 1 y el segundo codifica el lugar.

Con este nuevo esquema de codificación, el símbolo add LugarB 0x10 LugarB se codifica con la secuencia de 14 bits 0011 0 0001 0000 1. Si se asume que la representación se debe hacer en múltiplos de bytes, se añaden dos bits de relleno al finalpara un total de 16 bits o dos bytes: 0x3084.

Page 48: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

48 / 198

La pregunta que cabe hacerse ahora es ¿mantiene esta representación la propiedad de ser una codificación sistemática? Larespuesta es que sí pero con una modificación sustancial. El proceso de codificación queda perfectamente definido por las reglasanteriormente enunciadas. El proceso de decodificación sí requiere una estrategia diferente a las anteriores puesto que como eltamaño de la codificación es variable, su interpretación se debe realizar de forma incremental.

Los pasos a seguir consisten en obtener un primer byte y analizar los bits en orden para ver qué codifican. Dependiendo delos valores presentes se obtienen más o menos bits para decodificar los valores de los operandos. Así, por ejemplo, con larepresentación 0x3084 se observa que los dos primeros bits son cero, representando la operación add y que el siguiente bit esun uno, por lo que en lugar de obtener los ocho siguientes tan sólo se obtiene el siguiente que ahora sí se sabe que codifica unode los dos lugares. A continuación se procesan los bits restantes. El siguiente es un cero, con lo que es preciso procesar los ochobits siguientes, y acceder al siguiente byte. Una vez obtenidos los campos se concluye que no se necesitan más bytes y se obtieneel símbolo pertinente.

Este esquema de codificación mantiene tanto la propiedad de ser sistemático y como la premisa de representar las instruccionescon tamaños que sean múltiplos de bytes. A cambio resultan instrucciones de uno, dos y tres bytes dependiendo de los operandosque contengan.

Este último ejemplo ilustra las dos categorías en las que se dividen los lenguajes máquina de los procesadores comercialesateniéndose a la longitud de su codificación: formato fijo y formato variable.

Formato fijo: todas las instrucciones del lenguaje máquina tienen la misma longitud. Generalmente se dividen en porciones ycada porción codifica un elemento de la instrucción. Como principal ventaja ofrecen una decodificación muy rápida, pues lasreglas son muy simples. Como principal desventaja se desperdicia memoria al almacenarlas, pues algunos de los campos enalgunas instrucciones no son necesarios.

Formato variable: las instrucciones tienen tamaño diferente dependiendo de la información que contienen. Como principalventaja ofrece una representación muy compacta del código y por necesita menos memoria para ser almacenada. Como incon-veniente, el proceso de decodificación de una instrucción requiere múltiples pasos así como un acceso gradual a la secuenciade bits.

La complejidad del proceso de decodificación de una instrucción por el procesador tiene un impacto significativo en su velocidadde proceso. Esta fase es común a todas las instrucciones, y por tanto, si el proceso es demasiado lento, acaba afectando a lavelocidad global de ejecución. En la actualidad, estas dos categorías están presentes en el panorama de procesadores.

2.8.3. Descripción de un lenguaje máquina

La codificación de un lenguaje máquina implica un proceso de decodificación que se realiza en el procesador, y que por tantodebe ser implementado como un circuito digital. Pero para poder escribir programas en ese lenguaje máquina se precisa unadescripción detallada de cada una de las instrucciones así como las reglas que permiten su codificación en binario.

Toda descripción de un lenguaje máquina suele ir precedida por una descripción de la arquitectura del procesador que lo ejecuta.Esto es así porque en dicho lenguaje se permite la referencia a los elementos del procesador que se ofrecen para su programación.Tras la descripción de la arquitectura, la forma de describir el lenguaje máquina es agrupando sus operaciones. En lugar dedescribir todas las instrucciones posibles con todas las posibles combinaciones de operandos, se suelen describir juntas todasaquellas que tienen una funcionalidad similar. El apéndice A contiene la descripción del subconjunto de instrucciones máquinade la arquitectura IA-32 que serán consideradas a lo largo de este documento.

Todo procesador incluye, como parte de su definición, un conjunto de documentos con una descripción detallada de su arqui-tectura, del entorno de programación, de todas y cada una de sus instrucciones, así como de los mecanismos auxiliares que seofrecen para facilitar la ejecución de programas de usuario y del sistema operativo.

2.9. Ejercicios

1. ¿Cuántos bits se precisan para codificar 34 elementos? ¿y 32? ¿Se pueden codificar en binario 34 elementos con 8 bits?

2. ¿A partir de qué número de elementos se tienen que utilizar al menos 8 bits para su codificación binaria?

Page 49: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

49 / 198

3. Escribir sin utilizar la calculadora las potencias de 2 hasta 216. ¿Qué representa cada uno de esos números?

Utilizando únicamente los datos que aparecen en esta tabla y sin realizar operación aritmética alguna, ¿se pueden codificar5642 elementos con 13 bits?

4. De los siguientes números, dos de ellos están escritos incorrectamente, ¿cuáles son? ¿por qué?

100110

10032 (Incorrecto por el dígito 3)

5007

5034 (Incorrecto por el dígito 5)

5556

5. Calcular el equivalente en base 10 de los siguientes números:

437 = 31

11002 = 12

5346 = 202

7778 = 511

1009 = 81

6. Rellenar la siguiente tabla con la representación equivalente en las diferentes bases de los números en base 10 dados.

Base 10 Base 2 Base 5 Base 82910 11101 104 35

43210 110110000 3212 660945310 10010011101101 300303 22355

7. Rellenar la siguiente tabla con la representación equivalente en base 10 o binario de los números dados.

Binario Decimal10101000001 1345

110111 5511111111 255

101010 421000000000001 4097

100000 32

8. Rellenar la siguiente tabla con la representación equivalente en octal, hexadecimal o binario de los números dados.

Binario Octal Hexadecimal1011100101 01345 0x2E5

110111 67 371111001000110001 171061 0xF231

101010 52 2A100000111111 04077 83F

1011101011001010 135312 0xBACA

9. La representación de un número de 12 bits en octal es 7??3. Donde ‘?’ representa un dígito desconocido. ¿Cuáles de lassiguientes representaciones de ese mismo número en hexadecimal son posibles?

a. 0xE?3

b. 0xE?C

c. 0xF?3

Page 50: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

50 / 198

d. 0xF?C

10. ¿Qué intervalo de enteros permite representar la codificación en complemento a dos con 11 bits?

11. Realizar las operaciones 101100 - 100011 y 100011 + 001100 donde los operandos son números enteros representados encomplemento a 2 con 6 bits. Comprobar que los resultados obtenidos son consistentes con la representación en base 10 delos operandos.

12. Rellenar la siguiente tabla con la representación equivalente en complemento a dos con 10 bits o decimal de los siguientesnúmeros.

Complemento a 2 Decimal1001000011 -4451000110111 -4571000000001 -5110111010110 470

Fuera de rango -10121000000000 -512

2.10. Bibliografía

[Goldberg91] David Goldberg, What Every Computer Scientist Should Know About Floating-Point Arithmetic, Associationfor Computing Machinery, copyright © 1991 ACM.

Page 51: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

51 / 198

Capítulo 3

Almacenamiento de datos en memoria

En este capitulo se estudia el funcionamiento de la memoria RAM que utiliza el procesador para almacenar todos aquellos datosy código que precisa para la ejecución de un programa. También se estudia la técnica de la indirección por la que se manipulandirecciones de memoria que apuntan a otras direcciones en lugar de los propios datos.

3.1. La memoria RAM

Los circuitos digitales únicamente pueden procesar datos representados con ceros y unos, pero para ello deben estar almacenadosen otro circuito que permita a su vez su modificación. En el contexto de un ordenador este dispositivo suele ser la memoriaRAM (random access memory), un circuito que contiene en su interior una tabla que almacena información en cada uno de suscompartimentos.

Como toda tabla, es preciso saber dos de sus dimensiones: el tamaño de cada uno de sus elementos, y el número de elementosde los que dispone. Actualmente, las memorias convencionales almacenan la información en elementos de tamaño 1 byte. Por lotanto una memoria se puede ver como una tabla que contiene un determinado número de bytes. Los elementos de esta tabla estánnumerados con números naturales comenzando por el cero. El número correspondiente a cada una de los elementos se denomina‘dirección de memoria’ y se suele representar de forma abreviada por el símbolo ‘@’. Al conjunto de números que representan lasdirecciones de una memoria se le denomina su ‘espacio de direcciones’. La figura 3.1 ilustra la estructura, contenido y direccionesde una memoria RAM.

Page 52: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

52 / 198

Figura 3.1: Estructura de la memoria RAM

El acceso a los datos internos de la memoria viene determinado por el tamaño de sus celdas o elementos. Tal y como está estruc-turada, la memoria no ofrece acceso directo a cualquiera de sus bits, sino que es preciso primero obtener un byte y posteriormenteacceder al bit pertinente. Los procesadores incluyen en su lenguaje máquina las instrucciones necesarias para poder manipularlos bits de un byte. Si se quiere, por tanto cambiar un bit de un byte de memoria se debe leer el byte entero, utilizar instruccionespara cambiar su valor, y escribirlo de nuevo en memoria.

Internamente la memoria está implementada por un conjunto de transistores diseñados de tal forma que pueden almacenar lainformación dada. La unidad responsable de almacenar un bit de información se denomina ‘celda’. Un chip de memoria no esmás que un circuito que contiene un determinado número de celdas en cuyo interior se almacena un bit. Existen dos técnicas parael diseño de memoria: estática y dinámica.

La memoria RAM estática o SRAM es un circuito que una vez que se escribe un dato en una de sus celdas lo mantiene intactomientras el circuito reciba voltaje. En cuanto el voltaje desaparece, también lo hace la información. La celda de dicha memoriaestá compuesta por alrededor de seis transistores conectados de forma similar a un registro. El tiempo de lectura de una posiciónde memoria compuesta por ocho celdas suele ser del orden de decenas de nanosegundos (1 nanosegundo son 10-9 segundos).

La memoria RAM dinámica o DRAM es similar a la anterior pues también almacena información, pero su estructura interna esradicalmente diferente. La celda de memoria dinámica consta únicamente de un transistor y un condensador. Este último es elque almacena una carga, mientras que el transistor se utilizar para su carga y descarga. La celda de memoria dinámica almacenael valor 1 cuando el condensador está cargado, y cero cuando está descargado. El problema que presenta esta celda es que, a pesarde estar conectada continuamente a su alimentación, si el condensador almacena el valor 1 y no se realiza ninguna operación, sucarga se degrada hasta alcanzar el valor 0. Es decir, la celda de esta memoria no es capaz de mantener el valor uno durante untiempo arbitrario, sino que acaba perdiéndose. Pero, tal y como está diseñada la lógica de lectura, al leer una celda se refrescatotalmente su valor, y por tanto se recupera la pérdida de carga que pudiera haberse producido. El tiempo que tarda una celda enperder su información es del orden de milisegundos (1 milisegundo son 10-3 segundos).

Este comportamiento de las celdas puede parecer inútil para almacenar información, pero si el contenido se lee de forma perió-dica, la memoria dinámica se comporta de forma idéntica a la estática. Los circuitos de memoria dinámica incluyen la lógicanecesaria para que sus celdas sean continuamente leídas independientemente de las operaciones de lectura y escritura realizadaspor el procesador, de esta forma se garantiza que su contenido no se pierde. A esta operación se le conoce con el nombre de‘refresco’.

La mayoría de ordenadores utilizan memoria dinámica en su memoria principal y las principales razones para ello son el costey el espacio. La celda de memoria dinámica con un único transistor y un condensador es aproximadamente la cuarta parte del

Page 53: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

53 / 198

tamaño de la celda de SRAM que consta de alrededor de seis transistores. Pero, además de ser más pequeña, el proceso de diseñode una celda DRAM tiene un coste mucho menor por lo que los chips de memoria de gran capacidad de almacenamiento sediseñan con memoria dinámica.

La memoria estática tiene una clara ventaja frente a la dinámica y es que su tiempo de acceso es menor. En la realidad, en unordenador se utilizan ambos tipos de memoria. Para aquellos componente en los que se necesite mayor capacidad de almace-namiento la memoria dinámica es la idónea. En aquellos en los que se quiera un tiempo de acceso más reducido se utiliza lamemoria estática.

El diseño de un circuito de memoria es significativamente más simple que el de un procesador. La mayor parte del circuito sonréplicas de la celda que almacena un bit. Además de estas celdas, las memorias incluyen la lógica necesaria para el refresco (sison DRAM) y para realizar las operaciones de lectura y escritura.

3.2. Operaciones sobre memoria

Las dos operaciones que permite una memoria son lectura y escritura. En la operación de lectura, la memoria recibe una direccióny devuelve el byte contenido en el elemento con dicho número. En la operación de escritura la memoria recibe una dirección yun byte y sin devolver resultado alguno sobreescribe el byte en el elemento correspondiente. Otra forma posible de especificarestas operaciones es mediante la notación típica de un lenguaje de programación.

byte Lectura(dirección d): Dada una dirección de memoria devuelve el byte almacenado en dicho elemento.

void Escritura(dirección d, byte b): Almacena el byte b en el elemento de dirección d.

El contenido de los datos almacenados inicialmente en la memoria es indefinido. Si al encender el ordenador, la primera operaciónque se realiza es de lectura sobre memoria RAM, el resultado es indefinido. De esta propiedad se deduce que toda operación delectura se debe ejecutar sobre una posición de memoria que haya sido previamente escrita. La figura 3.2 muestra el efecto de unconjunto de operaciones sobre memoria.

Page 54: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

54 / 198

Figura 3.2: Operaciones sobre memoria

Al ser la memoria un circuito digital, todos sus datos deben ser codificados igualmente con ceros y unos y esto incluye a losparámetros que reciben las operaciones de lectura y escritura. El dato a leer o escribir es un byte y por tanto ya está codificado enbinario. Las direcciones también deben estar codificadas en binario, y como son números naturales (son positivos y comienzanpor cero) la codificación utilizada es base dos.

La lectura de un dato consiste en enviar a la memoria los bits que codifican una dirección, y la memoria devuelve ocho bits. Laoperación de escritura consisten en enviar a la memoria los bits que codifican una dirección y ocho bits de datos, y éstos últimosse almacenan en la posición especificada.

La codificación de las direcciones tiene una relación directa con el tamaño de la memoria. Todo byte en memoria tiene unadirección, y el número de bytes corresponde con el número máximo de dirección que se puede codificar. Al utilizar la codificaciónen base 2 se deduce que una memoria cuyas direcciones se codifican con n bits puede tener como máximo un tamaño de 2n bytescon direcciones desde 0 hasta 2n-1. En consecuencia, el tamaño T de memoria y el número n de bits que se utilizan para codificarlas direcciones están relacionadas por la ecuación

T = 2n

Debido a esta relación entre los bits que codifican una dirección y el número de elementos, las memorias suelen tener un tamañopotencia de 2. El coste de incluir un número determinado de bits hace que se aprovechen todas sus combinaciones.

El tamaño de la memoria se mide en múltiplos que no siguen las reglas convencionales de multiplicación por potencias de 10sino por potencias de 2. Así, un kilobyte son 210 bytes o 1024 bytes. Las unidades de medida del tamaño de memoria así comosus exponentes y los prefijos de su nomenclatura se muestran en la Tabla 3.1.

Page 55: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

55 / 198

Prefijo Símbolo Potenciakilo K 210

mega M 220

giga G 230

tera T 240

peta P 250

exa E 260

zetta Z 270

yotta Y 280

Tabla 3.1: Unidades de almacenamiento de información en bytes

3.3. Conexión entre memoria y procesador

La conexión entre la memoria y el procesador debe permitir que se realicen las operaciones de lectura y escritura de la formadescrita en la sección 3.2. Para ello son necesarios dos buses. El primero para que la memoria reciba la dirección del procesador,y el segundo para que el procesador envíe a la memoria el dato a escribir o que la memoria envíe al procesador el dato a leer.Además de estos dos buses el procesador debe notificar a la memoria el tipo de operación. La figura 3.3 muestra de formaesquemática cómo están conectadas estas señales.

Figura 3.3: Señales que conectan el procesador y la memoria

Dado el número de bits del bus de direcciones se puede deducir el tamaño de la memoria. ¿Se puede cambiar el tamaño de lamemoria de un ordenador? A la vista de las conexiones que se muestran en la figura 3.3 esto no es factible. El bus de direccioneses un conjunto de señales fijo y por tanto cambiar el tamaño de memoria significaría cambiar este número. Si un ordenadorduplica su memoria RAM necesita un bit adicional en su bus de direcciones.

Los buses se implementan como pistas de metal en un circuito impreso y sus extremos se conectan a los puertos de entrada delprocesador y la memoria, por lo que añadir un bit más al bus es una operación extremadamente compleja. Sin embargo, en losequipos actuales sí se ofrece la posibilidad de aumentar la memoria disponible mediante la inserción de circuitos adicionales.Esto es posible porque el bus de direcciones tiene más bits de los que son necesarios y además, el procesador comprueba que lasdirecciones de memoria utilizadas están dentro del rango correcto.

En general, en un procesador, el número de bits de los que consta el bus de direcciones es un parámetro fundamental de suarquitectura y no puede ser modificado. Por ejemplo, en la arquitectura IA-32, el bus de direcciones es de 32 bits, con lo que sepueden direccionar hasta un máximo de 4 gigabytes de memoria. En realidad, el procesador puede trabajar con un subconjuntode las direcciones posibles, es lo que se denomina ‘memoria real’ del ordenador frente a la ‘memoria posible’ que representa la

Page 56: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

56 / 198

memoria máxima que permite direccionar la anchura del bus de direcciones. La figura 3.4 ilustra esta situación para el caso en elque un procesador de tipo IA-32 dispone de una memoria real de 256 megabytes.

Figura 3.4: Memoria real y posible en un procesador con arquitectura IA-32

El procesador incluye un mecanismo por el que el límite de la memoria real es un dato conocido. Antes de realizar cualquieroperación sobre memoria se comprueba que la dirección está contenida entre ciertos límites. En caso de que así sea, la operaciónse realiza, y en caso contrario el procesador detiene el acceso y se produce una excepción en la ejecución.

En el caso concreto de la arquitectura IA-32, el bus de direcciones de 32 bits limita la memoria máxima que puede direccionar a4 gigabytes. Dada la progresión que ha tenido el precio de la memoria, ordenadores personales que tengan memoria mayor de 4gigabytes serán pronto una realidad. Un cambio en el bus de direcciones quiere decir una reorganización de la arquitectura enteradel procesador, y este ha sido el caso de la IA-32. La siguiente generación de procesadores ofrece un bus de direcciones y dedatos de 64 bits, por tanto con capacidad para direccionar un máximo de 16 exabytes (264 bytes).

3.4. Almacenamiento de datos

La única estructura que ofrece la memoria es la organización de sus elementos en bytes. Por tanto, para almacenar los datosque manipula un procesador es imprescindible saber de antemano su tamaño. El tamaño de algunos datos básicos viene definidopor la arquitectura del propio procesador. Por ejemplo, el lenguaje máquina de la arquitectura IA-32 contiene instruccionesmáquina para operar enteros de 32 bits. Esto no quiere decir que el procesador no pueda manejar enteros de otros tamaños, sinoque el procesador manipula estos de forma mucho más rápida y eficiente. Números de otros tamaños pueden ser manipuladosigualmente pero con un coste mayor en tiempo de ejecución.

Los lenguajes de programación de alto nivel como Java definen un conjunto de datos denominados ‘básicos’ y un conjuntode mecanismos para definir datos complejos en base a ellos. Como los programas escritos en estos lenguajes deben ejecutaren diferentes equipos con diferentes procesadores, es difícil definir el tamaño de los datos tal que se ajuste a todos ellos. Elcompilador se encarga de transformar las operaciones escritas en lenguaje de alto nivel en las instrucciones más adecuadas para

Page 57: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

57 / 198

manipular los datos en el procesador pertinente. La Tabla 3.2 muestra los tipos de datos básicos definidos en Java así como sutamaño.

Tipo Contiene Tamaño Rangoboolean true, false 1 bitbyte Entero 8 bits [-128, 127]char Caracter Unicode 16 bits [0, 65535]short Entero 16 bits [-32768, 32767]

int Entero 32 bits [-2147483648,2147483647]

long Entero 64 bits[-9223372036854775808,9223372036854775807]

float IEEE-754 Coma Flotante 32 bits [±1.4012985E-45,±3.4028235E+38]

double IEEE-754 Coma Flotante 64 bits[±4.94065645841246544E-324,±1.7976931348623157E+308]

Tabla 3.2: Tipos de datos básicos en el lenguaje Java

La regla para almacenar datos en memoria es utilizar tantos bytes como sean necesarios a partir de una dirección de memoria. Enadelante, la posición de memoria a partir de la cual está almacenado un dato se denominará su dirección de memoria. De formaanáloga, cuando se dice que un dato está en una posición de memoria lo que significa es que está almacenado en esa posición ylas siguientes que se precisen.

3.4.1. Almacenamiento de booleanos

Los valores booleanos, a pesar de ser los más sencillos, no son los más fáciles de almacenar. La memoria permite el acceso agrupos de 8 bits (1 byte) por lo que almacenar un único bit significa utilizar una parte que no es directamente accesible sinoque requiere procesado adicional. Por este motivo se intenta almacenar varios booleanos juntos y de esta forma maximizar lainformación contenida en un byte. Esta estrategia se utiliza cuando es fácil saber la posición de un booleano dentro del byte. Enel caso de que esto no sea posible, se utiliza un byte para almacenar un único bit, con lo que los 7 bits restantes se desperdician.La figura 3.5 muestra estas dos posibles situaciones.

Figura 3.5: Almacenamiento de booleanos

Si un conjunto de 8 booleanos se agrupan para ocupar un byte por entero, para acceder a un valor concreto se precisan ins-trucciones especiales contenidas en prácticamente todos los lenguajes máquina de los procesadores y suelen estar basadas eninstrucciones lógicas tales como la conjunción o la disyunción. En el caso de la arquitectura IA-32, mediante operaciones comoand u or, la utilización de máscaras y la consulta de los bits de estado se pueden manipular los booleanos en un byte.

Page 58: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

58 / 198

3.4.2. Almacenamiento de caracteres

Tal y como se ha visto en el capítulo 2, la codificación ASCII utiliza 8 bits para representar caracteres. La forma de almacenarestos datos en memoria es simplemente utilizando un elemento o byte para cada letra. La figura 3.6 muestra cómo se almacenanen memoria un conjunto de letras representadas por su valor en ASCII.

Figura 3.6: Almacenamiento de un string

Todo símbolo tiene su correspondiente código, incluido el espacio en blanco (0x20). Si la codificación utilizada fuese UnicodeUTF-16, cada símbolo ocupa dos posiciones consecutivas de memoria en lugar de una.

3.4.3. Almacenamiento de enteros y naturales

Para almacenar un número entero o natural en memoria es imprescindible saber su tamaño en bytes. Las representaciones másutilizadas incluyen tamaños de 2, 4, 8 o hasta 16 bytes. Siguiendo la regla genérica de almacenamiento, se utilizan tantos bytesconsecutivos a partir de una posición dada como sean precisos. El tamaño de esta representación no sólo influye en el lugarque ocupan en memoria sino también en el diseño de las partes del procesador que realizan las operaciones. Por ejemplo, si losenteros se representan con 32 bits, el procesador suele incluir una unidad aritmético lógica con operandos de 32 bits.

Pero en esta representación es esencial saber en qué orden se almacenan estos bytes. Dado un entero que ocupa n bytes a partirde la posición p de memoria, se pueden almacenar estos bytes comenzando por el byte menos significativo del número o porel más significativo. Estas dos posibilidades son igualmente factibles. Considérese el ejemplo de un procesador que manipulanúmeros enteros de 32 bits. La representación del entero 70960543 en complemento a 2 es 0x043AC59F y se almacena a partirde la posición de memoria 0x00001000. La figura 3.7 muestra las dos posibles formas de almacenamiento dependiendo de sise seleccionan los bytes de menor a mayor significación o al contrario.

Page 59: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

59 / 198

Figura 3.7: Almacenamiento de enteros en memoria

A estas dos formas de almacenar números enteros o naturales de más de un byte en tamaño se les conoce con el nombre de ‘littleendian’ y ‘big endian’. El primero almacena los bytes de menor a mayor significación, mientras el segundo almacena primero elbyte de mayor significación.

Cada procesador utiliza un único método de almacenamiento para todos sus enteros o naturales, y en la actualidad coexistenprocesadores que utilizan little endian con otros que utilizan big endian.

El problema de la existencia de ambas políticas de almacenamiento surge cuando dos procesadores intercambian números. Comouna secuencia de bytes es interpretada de forma diferente por los dos procesadores, se debe realizar un proceso de traducciónpor el que se garantiza que ambos manipulan los mismos datos. La figura 3.8 muestra cómo la interpretación de un número de 4bytes con ambas formas ofrece resultados diferentes.

Figura 3.8: Interpretación de bytes en little endian y big endian

Page 60: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

60 / 198

Existen numerosos argumentos a favor y en contra de ambas notaciones pero ninguno de ellos es concluyente. Quizás el másintuitivo a favor de la notación little endian es que si un número se almacena siguiendo este esquema y su representación seextiende en tamaño, únicamente es necesario utilizar más posiciones de memoria sin reorganizar los bytes. En cambio, en el casode big endian, la misma operación requiere almacenar los bytes en diferentes posiciones de memoria.

3.4.4. Almacenamiento de instrucciones

El almacenamiento de instrucciones consiste simplemente en utilizar posiciones consecutivas de memoria para almacenar losbytes de la codificación de cada una de ellas. Una secuencia de instrucciones, por tanto, requiere tantas posiciones de memoriacomo la suma de los tamaños de cada una de las codificaciones.

Tal y como se ha descrito en la sección 2.8.2, existen dos tipos de lenguajes máquina. Los procesadores con formato fijo deinstrucción almacenan las instrucciones en memoria en porciones idénticas. En este caso, dada una porción de memoria quecontiene una secuencia de instrucciones es muy fácil acceder a una de ellas de forma arbitraria, pues todas ocupan lo mismo. Elcaso de instrucciones de formato variable es ligeramente más complejo. Dada una porción de memoria, para saber qué posicionesocupa cada instrucción es preciso interpretar la información que éstas codifican. Esto es precisamente lo que hace el procesadoral comienzo de la ejecución de cada instrucción, solicita de memoria tantos bytes como sean necesarios para obtener toda lainformación referente a la instrucción. Una vez concluida esta fase, la siguiente instrucción comienza en la posición contigua dememoria. La figura 3.9 muestra un ejemplo de cómo se almacenan los dos posibles formatos de instrucción.

Figura 3.9: Almacenamiento de instrucciones en formato fijo y variable

Page 61: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

61 / 198

En el almacenamiento de instrucciones no es preciso distinguir entre los estilos big endian o little endian pues en la codificaciónno existen bytes más significativos que otros. El convenio que se utiliza es que se escriben los bytes de la instrucción en el mismoorden en el que están almacenados en memoria.

3.4.5. Tamaño de datos en operaciones de lectura y escritura

La memoria almacena un byte en cada una de sus posiciones que a su vez tiene una dirección única. El funcionamiento de lamemoria está totalmente definido mediante esta estructura. Sin embargo, cuando la memoria forma parte del conjunto de unordenador, el tiempo que tarda en realizar una operación es mucho mayor comparado con el que tarda el procesador en ejecutaruna instrucción. En otras palabras, los accesos a memoria requieren tanto tiempo que retrasan la ejecución de las instruccionesdel procesador.

Existen múltiples decisiones de diseño en la arquitectura de un procesador que se utilizan para paliar este retraso. De entre ellas,una de las más efectivas es realizar las operaciones en memoria en paquetes de información mayores de un byte. Es decir, cuandoel procesador lee y escribe en memoria, en lugar de trabajar con un único byte, los datos están compuestos por más de un byte enposiciones consecutivas. Esta técnica tiene la ventaja de que un único acceso a memoria para, por ejemplo, lectura, proporcionamás de un byte en posiciones consecutivas. El inconveniente es que es posible que en ciertas ocasiones, se obtenga de memoriamás información de la estrictamente necesaria.

Generalmente, todo procesador ofrece la posibilidad de escribir un cierto tamaño de datos en bytes (mayor que uno) en una únicaoperación de memoria. La forma en que se implementa este mecanismo es utilizando múltiples módulos de memoria. Por ejem-plo, supóngase que se quiere manipular la memoria tal que las operaciones se hagan en grupos de cuatro bytes simultáneamente.El ejemplo que se describe a continuación se puede realizar con cualquier agrupamiento de información que sea potencia de dos.

La primera decisión es almacenar los datos en cuatro módulos o circuitos independientes de memoria de tal forma que la posición0 de memoria se almacena en el primer módulo, la posición 1 en el segundo, y así sucesivamente. La quinta posición de memoriase almacena de nuevo en el primer módulo.

Con este esquema, el módulo en el que está almacenado el dato de la posición p se obtiene mediante la expresión p % 4. Laconsecuencia de este patrón de almacenamiento es que se puede acceder a cuatro bytes de memoria en el tiempo en el que se leeun byte. Dada una dirección de memoria, cada módulo devuelve un byte y se obtienen los cuatro en el tiempo de retardo de unúnico módulo pues todos trabajan en paralelo. Por tanto, dada una dirección de memoria d, con esta técnica, la memoria es capazde devolver los datos desde la posición d / 4 (donde esta división es división entera) a la posición d / 4 + 3 en el tiempo de retardode un único módulo.

Otra interpretación de esta organización es que la memoria contiene grupos de 4 bytes y cada uno de ellos está almacenado en laposición d / 4. Pero, dada la dirección d, ¿como se obtiene el número d / 4?. La dirección de memoria está codificada en base 2,y como esta operación es una división por una potencia de la base, equivale a tomar la dirección ignorando los dos bits de menospeso, pues 4 = 22. En realidad, dada la dirección d el cociente de la división entera entre cuatro es el número de grupo mientrasque el resto de esta división representa el byte del grupo de 4 al que se refiere d. La figura 3.10 muestra cómo implementar esteesquema de acceso en una memoria con direcciones de 32 bits.

Page 62: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

62 / 198

Figura 3.10: Acceso a memoria en grupos de 4 bytes

Cada módulo de memoria recibe 30 de los 32 bits de la dirección. Esto es así porque la memoria consta de exactamente 230

grupos de cuatro bytes y cada módulo de memoria provee un byte de cada grupo. Con esta configuración se obtienen cuatro bytesen el tiempo en el que un módulo lee uno de sus bytes, pues los cuatro acceden a su dato respectivo de forma paralela. Ademásde los componentes que se muestran en la figura 3.10, la nueva memoria contiene la lógica necesaria para igualmente permitir lalectura y escritura de un único byte en lugar de cuatro.

Los accesos a esta memoria a direcciones que son múltiplos de 4 se denominan accesos alineados. Pero, ¿qué sucede si elprocesador quiere acceder a 4 bytes consecutivos de esta memoria pero que no comienzan en una posición múltiplo de 4? Elparalelismo se obtiene porque si cada módulo lee la misma dirección de memoria y ofrece su correspondiente byte, pero si elprocesador requiere cuatro bytes que no están en el mismo grupo, este esquema no funciona puesto que no todos los módulosdeben leer de la misma dirección. A este tipo de accesos se le denominan accesos no alineados. En tal caso, la memoria seocupa internamente de realizar cuantos accesos sean necesarios para devolver los cuatro bytes que requiere el procesador. No seprecisan más de dos accesos a memoria para servir cualquier petición de cuatro bytes consecutivos del procesador. Por ejemplo,si el procesador requiere los datos en las posiciones 4 * d + 3 a 4 * d + 6, el procesador selecciona el último byte del grupo condirección 4 * d y los tres primeros del grupo con dirección 4 * (d + 1). La figura 3.11 muestra los dos accesos a memoria paraobtener los datos requeridos.

Page 63: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

63 / 198

Figura 3.11: Acceso doble para obtener 4 bytes consecutivos

En el caso concreto de la arquitectura IA-32, se define un bus de direcciones y un bus de datos ambos de tamaño 32 bits. Elprocesador puede leer o escribir 4 bytes de datos en memoria de forma simultánea.

3.5. Almacenamiento de tablas

En la sección 3.4 se ha visto cómo los tipos de datos básicos se almacenan en memoria, pero los programas manipulan estructurasde datos más complejas compuestas a su vez por datos básicos. Un ejemplo de estas estructuras son las tablas o arrays. Una tablaes un conjunto de datos agrupados de forma que cada uno de ellos puede ser accedido a través de un índice que se correspondecon un número natural. El primer elemento está en la posición con índice cero y el último en la posición con índice igual alnúmero de elementos de la tabla menos uno. En los lenguajes de programación tales como C o Java, si una tabla de elementos sedenomina tabla, el elemento en la posición i se accede mediante la expresión tabla[i]. ¿Cómo se almacenan estos datosen memoria de forma que puedan ser accedidos por el procesador?

Al igual que en el caso de los datos básicos, la estrategia consiste en utilizar posiciones consecutivas de memoria para almacenarlos elementos. Si una tabla contiene n elementos y cada uno de ellos se codifica con m bytes, el espacio total ocupado por latabla es de n * m bytes. Dada la dirección de memoria d a partir de la cual se almacena la tabla y el tamaño m en bytes decada elemento la dirección donde está almacenado el elemento en la posición p se obtiene sumando a d los bytes que ocupan loselementos anteriores, o lo que es lo mismo d + (p * m). La figura 3.12 ilustra cómo se realiza este cálculo.

Page 64: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

64 / 198

Figura 3.12: Dirección de un elemento de una tabla

Considérese, por ejemplo, una tabla de 4 enteros almacenada en la memoria de un procesador con arquitectura IA-32 a partirde la posición 0x100 y con los números 0x34AF89C4, 0x583B7AF1, 0x97FA7C7E, 0x14C8B9A0 almacenados en esemismo orden. La figura 3.13 muestra su disposición en memoria.

Figura 3.13: Ejemplo de almacenamiento de una tabla de enteros de 32 bits en memoria

Pero para manipular tablas de datos no sólo basta con almacenar los elementos en posiciones consecutivas. Considérese elsiguiente ejemplo. Se dispone de una tabla de enteros y se debe calcular la suma total de sus elementos. Para ello se comienzasumando el primer elemento, a él se le suma el segundo, a este resultado el tercero, y así sucesivamente. Pero ¿cómo se sabe quese ha llegado al último elemento? Para cualquier tabla, además de la dirección de comienzo y el tamaño de sus elementos, espreciso saber el número de elementos que contiene.

Existen dos mecanismos para saber cuántos elementos contiene una tabla. El primero de ellos consiste en depositar como últimoelemento, un valor que denote el final. Por ejemplo, considérese una tabla de letras que almacena una frase. Cada letra se almacenacon su codificación en ASCII (ver sección 2.8.1), por lo que cada letra ocupa un byte. Al final de la tabla se incluye un byte convalor 0 que está reservado específicamente en ASCII para codificar el final de una secuencia de letras. Para recorrer todos loselementos de esta tabla basta con escribir un bucle que se detenga cuando encuentre el valor cero.

Pero la técnica de depositar un valor concreto como último elemento no funciona para todos los tipos de datos. ¿Qué sucedeen el caso de una tabla de números enteros? Cada elemento se codifica con su representación en complemento a 2 que utilizala totalidad de posibles combinaciones de bits. Por tanto, no es posible utilizar un valor específico para denotar el final de latabla pues se confundiría con la representación de su número entero correspondiente. Para saber el tamaño, simplemente hay quealmacenar este valor en una posición adicional de memoria. De esta forma, si se desea acceder a todos los elementos de la tabla

Page 65: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

65 / 198

de forma secuencial basta con escribir un bucle que compare la posición del elemento con el tamaño. Tanto esta técnica como laanterior se utilizan de forma frecuente en los lenguajes de programación de alto nivel.

3.5.1. Almacenamiento de tablas en Java

El lenguaje de programación Java garantiza que el acceso a los elementos de un array se realiza siempre con un índice correcto.Dado que toda tabla en Java tiene su primer elemento en la posición con índice cero, el índice i con el que se accede a una tablade n elementos debe cumplir 0 ≤ i < n.

Pero esta comprobación sólo se puede realizar mientras un programa está en ejecución. Supóngase que un programa Java contienela expresión tabla[expresión]. ¿Cómo se puede garantizar que el acceso a la tabla es correcto? La solución consiste enque antes de que el programa ejecute esta expresión se comprueba que su valor está en los límites correctos, en cuyo caso elacceso se realiza sin problemas. Si el índice no está entre los límites permitidos el programa produce una excepción del tipoArrayIndexOutOfBounds.

Para implementar este mecanismo no sólo toda tabla en Java debe tener almacenado su tamaño sino que cada acceso va precedidode la comprobación del valor del índice. Se necesita, por tanto, un mecanismo que almacene los datos de una tabla y su tamañode forma compacta y que además permita una eficiente comprobación de los accesos a sus elementos.

La solución en Java consiste en almacenar el tamaño de una tabla junto con sus elementos en posiciones consecutivas de memoria.De entre todas las posibilidades de organizar estos datos, la más lógica es poner el tamaño en las primeras posiciones de memoriaseguido de los elementos. La figura 3.14 muestra cómo se almacena en memoria una tabla de seis enteros de 32 bits en formatolittle endian a partir de la posición 0x100.

Figura 3.14: Almacenamiento de una tabla de seis enteros en Java

Antes de cada acceso al elemento i que ocupa t bytes de una tabla con s elementos almacenada a partir de la posición d, elprograma escrito en Java realiza las siguientes operaciones:

Obtiene el entero s almacenado a partir de la posición d.

Comprueba que 0 ≤ i. En caso de que no sea así produce una excepción.

Comprueba que i < s. En caso de que no sea así produce una excepción.

Calcula la dirección donde está el elemento i como d + 4 + (t * i).

3.6. Almacenamiento de direcciones de memoria

Supongamos que la memoria utilizada tiene un tamaño de 4 Gigabytes y por tanto sus direcciones se representan con 32 bits. Lasdirecciones de memoria son números naturales en el rango [0, 232 - 1]. Pero este número natural es susceptible de ser almacenado

Page 66: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

66 / 198

él mismo en memoria. Es decir, se puede almacenar la representación binaria de una dirección de memoria en la propia memoria.Al tener un tamaño de 32 bits o 4 bytes, se utilizan para ello cuatro posiciones de memoria consecutivas.

Una dirección de memoria, por tanto, se puede considerar de dos formas posibles: o como una dirección de una celda de memoria,o como un número natural susceptible de ser manipulado como tal. Supóngase que en la posición de memoria 0x00000100se encuentra almacenado el número entero de 32 bits 0x0153F2AB y que en la posición 0x00000200 se debe almacenar ladirección de dicho número. Para ello se almacena, a partir de la posición 0x00000200 el número 0x00000100 utilizando loscuatro bytes a partir de esa posición y se hace en orden creciente de significación al utilizar el esquema little endian. El resultadose ilustra en la figura 3.15.

Figura 3.15: Dirección de memoria almacenada como número natural

Tras almacenar la dirección de memoria de un dato en la posición 0x00000200, ¿es posible obtener de nuevo el número 0-x0153F2AB? La respuesta es afirmativa, pero no de forma inmediata, se debe obtener de memoria primero los cuatro bytesalmacenados en la posición 0x00000200 y utilizarlos como una dirección de memoria de donde obtener los cuatro bytescontenidos en la posición 0x00000100. El acceso a este último dato se ha realizado de forma indirecta, es decir, mediante unacceso previo a memoria para obtener la dirección del dato final. Utilizando la notación funcional de operaciones sobre memoria,el acceso al dato se logra ejecutando Lectura(Lectura(0x00000200)).

A este mecanismo de acceso a un dato en memoria a través de su dirección a su vez almacenada en otra posición se le conocecon el nombre de ‘indirección’. En el ejemplo anterior se dice que el dato almacenado en la posición 0x00000200 apunta aldato 0x0153F2AB. La figura 3.16 ilustra esta situación.

Figura 3.16: Una posición de memoria ‘apunta a’ otra

El mecanismo de indirección se puede encadenar de manera arbitrariamente larga. La dirección que contiene la dirección de

Page 67: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

67 / 198

un dato, a su vez se puede almacenar de nuevo en memoria. En tal caso, para acceder al dato final se requieren dos accesos amemoria en lugar de uno. Por tanto, es posible almacenar las direcciones tal que haya que seguir una cadena de indireccionespara en última instancia acceder al dato. La figura 3.17 muestra una distribución de datos tal que la posición 0x00000100contiene ‘la dirección de memoria de la dirección de memoria de la dirección de memoria del dato’.

Figura 3.17: Indirección múltiple para acceder a un dato

De la técnica de indirección se deriva que en memoria no sólo se almacenan datos (naturales, enteros, coma flotante, letras, etc.)sino también direcciones de memoria. Todos estos datos, a efectos de almacenamiento y su manipulación por el procesador, noson más que una secuencia de bytes en diferentes celdas. El que una secuencia de bits determinada se interprete como un númeroo como una dirección queda totalmente bajo el control del programador. En los programas escritos en ensamblador es precisosaber qué dato está almacenado en qué posición de memoria pero el propio lenguaje no aporta mecanismo alguno que compruebeque se el acceso se hace de forma correcta. Si por error en un programa se obtiene un dato de 32 bits de memoria y se interpretacomo una dirección cuando en realidad es un dato numérico o viceversa, lo más probable es que el programa termine de formabrusca o con resultados incorrectos.

3.6.1. Ejemplos de indirección

El almacenar una dirección en memoria no parece a primera vista un mecanismo útil, pues esta cumple un único papel que es elde apuntar al dato en cuestión. Sin embargo, esta técnica se utiliza con frecuencia en la ejecución de programas.

Page 68: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

68 / 198

Ejemplo 3.1 Almacenamiento de una tabla de stringsSupóngase que se dispone de un conjunto de n strings almacenados en otras tantas posiciones de memoria. Aunque las letrasde cada string están almacenadas en posiciones consecutivas, los strings no están uno a continuación de otro sino en zonas dememoria dispersas. Se quiere imprimir estos strings en orden alfabético. El primer paso es ordenar los strings para a continuaciónimprimir cada uno de ellos por orden.Para ordenar los strings hay dos opciones, o se manipulan todos los caracteres de cada uno de ellos, o se manipulan sus direccionesde comienzo. Es decir, en lugar de tener los strings ordenados alfabéticamente y almacenados en posiciones consecutivas dememoria, se almacenan por orden las direcciones de memoria de comienzo de cada string y se ordenan en base a las letras quecontienen. Esta estructura se ilustra en la figura 3.18.

Figura 3.18: Tabla con direcciones de comienzo de strings

La ordenación los strings se puede realizar sin mover ninguna de las letras en memoria. La tabla resultante contiene en cada unode sus elementos una indirección a un string, es decir, la dirección en la que se encuentra el string pertinente. Para imprimir losstrings en orden alfabético se itera sobre los elementos de la tabla y mediante doble indirección se accede a las letras de cadastring.

Page 69: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

69 / 198

Ejemplo 3.2 Referencias en el lenguaje JavaEl lenguaje de programación Java utiliza el mecanismo de indirección para acceder a los datos almacenados en un objeto.Supóngase que se ha definido una clase con nombre Dato que a su vez contiene un campo de acceso público, entero y connombre valor. Se ejecuta la siguiente porción de código.

Línea Código

12345

6

Dato obj1, obj2;obj1 = new Dato();obj1.valor = 3;obj2 = obj1;obj2.valor = 4;

System.out.println(obj1.valor)

¿Qué valor imprime por pantalla la última línea? El código asigna al campo valor de obj1 el valor 3, a continuación seproduce la asignación obj2 = obj1, luego se asigna el valor 4 al campo valor de obj2 y se imprime el mismo campo perode obj1. Al ejecutar este fragmento de código se imprime el valor 4 por pantalla. La línea que explica este comportamiento esla asignación obj2 = obj1. En Java, todo objeto se manipula a través de una ‘referencia’. Las variables obj1 y obj2 sonreferencias y la asignación obj1 = obj2 no transfiere el contenido entero de un objeto a otro, sino que se transfiere el valor dela referencia. Por tanto, al ejecutar esta asignación, obj2 se refiere al mismo objeto que obj1 y por eso la última línea imprimeel valor 4.El mecanismo interno que se utiliza a nivel de lenguaje máquina para representar las referencias está basado en el concepto deindirección. Cuando se crea un objeto se almacenan sus datos en memoria. Cuando un objeto se asigna a una referencia esta pasaa contener la dirección de memoria a partir de la cual está almacenado. La asignación obj2 = obj1 transfiere la dirección dememoria contenida en obj1 al contenido de obj2. Cualquier modificación que se haga a través de la referencia obj1 afectapor tanto al objeto al que apunta obj2 pues ambas referencias apuntan al mismo objeto. La figura 3.19 ilustra cómo se asignanlos valores en memoria para este ejemplo.

Figura 3.19: Dos referencias en Java que apuntan al mismo objeto

El objeto está ubicado en una posición arbitraria de memoria (en la figura 3.19 es la posición 0x00000100). En dos posicionesde memoria adicionales se almacenan las referencias obj1 y obj2. La primera de ellas recibe su valor al ejecutarse el constructorde la clase. La segunda recibe el mismo valor cuando se ejecuta la asignación. A partir de este momento, cualquier modificaciónrealizada en el objeto a través de obj1 será visible si se consulta a través de obj2.

Page 70: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

70 / 198

Ejemplo 3.3 Doble indirección con referencias en el lenguaje JavaLas referencias en Java se utilizan, por tanto, como indirecciones a memoria. Pero las clases definidas en Java pueden contener ensu interior campos que sean referencias a otros objetos. Por ejemplo, si se define una segunda clase Dato2 en cuyo interior existeun campo con nombre c1 de la clase Dato, este campo es una referencia a un objeto. Supóngase que se ejecuta la siguienteporción de código.

Línea Código

123

4

Dato2 obj2;obj2 = new Dato2();obj2.c1 = new Dato();

obj2.c1.valor = 4;

En este caso la referencia obj2 apunta a un objeto de la clase Dato2 que a su vez contiene en su interior una referencia a unobjeto de la clase Dato. Para ejecutar la última línea en la que se asigna el valor 4 al campo valor es preciso realizar una dobleindirección. La referencia obj2 contiene la dirección del objeto de la clase Dato2, y este a su vez contiene en su interior unareferencia que contiene la dirección del objeto de la clase Dato. Tras esta doble indirección se asigna el valor 4 a dicho dato. Lafigura 3.20 muestra el acceso a este dato a través de la doble indirección.

Figura 3.20: Acceso a un dato mediante doble indirección

3.7. Ejercicios

1. Diseñar una memoria tal que ofrezca al procesador la capacidad de acceder a ocho bytes consecutivos de memoria en eltiempo en el que se lee un único byte. El diseño debe incluir el tamaño de los buses así como su estructura interna.

2. La memoria de un procesador ofrece acceso a cuatro bytes consecutivos de memoria mediante un único acceso siempre ycuando estén almacenados a partir de una posición que es múltiplo de cuatro. En este procesador se ejecutan dos programascon idénticas instrucciones que acceden a un array de un millón de enteros de tamaño 32 bits. El primer programa realizaun total de un millón de accesos a la zona de memoria en la que está almacenado el array. El segundo programa realizaexactamente el doble de accesos a memoria a la misma zona, ¿cómo es esto posible?

3. Supongamos un procesador que permite operaciones en memoria en bloques de 32 bits (4 bytes). Se ejecutan las siguientesinstrucciones:

Write(0x100, 0x01234567)

Write(0x101, 0x89ABCDEF)

Write(0x102, 0xFFFFFFFF)

Read(0x100)

Page 71: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

71 / 198

¿Cuál es el resultado de la última operación?

4. Una tabla en Java almacena referencias a objetos. Estas referencias ocupan 32 bits cada una. La tabla contiene 23 elementosy está almacenada a partir de la posición 300 de memoria. ¿En qué dirección está almacenada la referencia del elementoen tabla[21]? ¿Y la referencia del elemento tabla[23]?

5. ¿Cuántas posiciones de memoria reserva la ejecución de la expresión Java int[] tabla = new int[49]?

6. Supongase un ordenador con memoria principal de 16 Kilobytes (1 Kilobyte = 1024 bytes). Explicar cuantos bits de datosy dirección se precisan y por qué en los siguientes supuestos:

a. La memoria lee y escribe la información en grupos de 8 bits:

b. La memoria lee y escribe la información en grupos de 32 bits:

Page 72: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

72 / 198

Capítulo 4

Arquitectura IA-32

En este capítulo se estudian los componentes básicos de la arquitectura IA-32: registros, palabra de estado, tamaño del bus, etc.

La arquitectura de un procesador consiste de los elementos internos que permiten la ejecución de las instrucciones de su lenguajemáquina. La complejidad de un procesador actual es demasiado grande para poder ser estudiada en su totalidad. A modo dereferencia, los modelos del procesador Pentium producidos a comienzos del año 2004 contienen alrededor de 50 millones detransistores (en diciembre de 1974, el procesador 8080 producido por la misma empresa tenía 6000 transistores). Este tipo decircuitos se diseñan a lo largo de varios años y por grandes equipos de diseñadores. La figura 4.1 muestra a la izquierda la imagendel Pentium 4 del año 2001 así como su tamaño1. En la parte derecha se muestra el mismo chip comparado con una moneda deun céntimo de euro (16.25 mm de diámetro).

1Scott Thompson y otros. 130nm Logic Technology Featuring 60nm Transistors, Low-K Dielectrics, and Cu Interconnects. Intel Technology Journal, volumen6, número 2, Mayo 2002.

Page 73: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

73 / 198

Figura 4.1: Pentium 4 Northwood (Dic. 2001). Fuente: Intel Technology Journal, vol. 6, núm. 2.

La complejidad de diseño de estos circuitos viene acompañada por una tecnología de fabricación que permite un empaquetadoen dispositivos de tamaño extremadamente reducido. La figura 4.2 muestra el aspecto de un Pentium 4 ya empaquetado y listopara ser instalado en una placa de circuito impreso.

Page 74: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

74 / 198

Figura 4.2: Chip con un procesador Pentium 4 en su interior

Se explican a continuación, los elementos básicos de la arquitectura IA-32 para entender el funcionamiento y la manipulación dedatos sin analizarlo en su totalidad. Se aplica, por tanto, un nivel de abstracción a la arquitectura real y se estudian sólo aquelloscomponentes necesarios para la comprensión de las instrucciones que permiten la ejecución de operaciones básicas tales comocálculo aritmético, implementación de condicionales, llamadas a subrutinas, paso de parámetros, gestión de la pila, etc.

Para el desarrollo de aplicaciones avanzadas sobre un procesador de estas características sí es preciso tener un conocimientomás profundo de la arquitectura. En tal caso, los documentos en los que se encuentra el nivel de detalle necesario para estatarea los proveen los mismos fabricantes. En lugar de explicar en detalle un procesador en concreto, generalmente las empresasfabricantes de procesadores crean una arquitectura concreta y luego fabrican múltiples chips todos ellos compatibles con esaarquitectura pero con diferentes prestaciones. En el caso concreto de la arquitectura IA-32, la empresa fabricante ofrece tresdocumentos de información agrupados bajo el nombre de IA-32 Intel Architecture Software Developer’s Manual que contienentodos los aspectos del funcionamiento de la arquitectura denominada IA-32. El primer volumen ofrece una visión global de laarquitectura, el formato de instrucciones, el entorno de ejecución del procesador, los tipos de datos, las técnicas utilizadas paralas llamadas a procedimientos y las extensiones especiales incluidas en esta arquitectura. El segundo volumen describe todas ycada una de las instrucciones máquina contenidas en la arquitectura. El tercer volumen contiene la información necesaria parautilizar el procesador en un sistema completo, como por ejemplo, los bits de control y estado, gestión de memoria, esquema deprotección, manejo de excepciones e interrupciones, gestión de múltiples procesadores, memoria cache, etc.

4.1. El entorno de ejecución de la arquitectura IA-32

En esta sección se describe el entorno de ejecución del procesador tal y como se ve desde un programa escrito en lenguajeensamblador. Este entorno consta, además de otros componentes, de un conjunto de registros, un espacio de direcciones, unregistro de condiciones y estado, y el registro contador de programa.

En adelante las diferentes unidades de información que es capaz de manipular el procesador se denominarán utilizando lostérminos que se muestran en la Tabla 4.1. Todos ellos son utilizadas por algún componente del procesador y sus tamaños sontodos múltiplos de bytes.

La figura 4.3 muestra los tamaños relativos de estos datos así como la numeración seguida para referirse a los bytes de los queestán compuestos. Nótese que los bits se comienzan a numerar por el cero el menos significativo.

Page 75: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

75 / 198

Denominación TamañoByte 8 bitsWord 16 bits, 2 bytes

Doubleword 32 bits, 4 bytesQuadword 64 bits, 8 bytes

Double Quadword 128 bits, 16 bytes

Tabla 4.1: Nomenclatura para los tamaños de información

Figura 4.3: Tipos de datos del procesador

4.1.1. Espacio de direcciones

La arquitectura IA-32 permite gestionar el acceso a memoria de dos formas posibles denominadas modelo lineal y modelosegmentado.

En el modelo lineal la memoria aparece como un único espacio contiguo de tamaño máximo 232 bytes o 4 gigabytes. En él sealmacenan todos los datos, código y demás información necesaria para la ejecución de los programas. Las direcciones en estemodelo tienen un tamaño fijo de 32 bits.

El modelo segmentado es más complejo. El espacio de direcciones se organiza como un grupo de espacios de direccionesindependientes denominados segmentos. La razón por la que se propone esta técnica es para separar código, datos e informaciónadicional de los programas en diferentes segmentos. La dirección para acceder a un byte en este modelo consta de dos partes,un identificador de segmento y un desplazamiento dentro de ese segmento. El procesador puede utilizar hasta un total de 16.383segmentos y cada uno de ellos de un tamaño máximo de 4 gigabytes. La ventaja de gestionar la memoria de esta forma es elincremento en la seguridad en la ejecución de programas. Mediante la colocación de código y datos en segmentos separados sepuede forzar una política de acceso a datos únicamente dentro del mismo segmento y así detectar fácilmente accesos a zonas dememoria incorrectas.

En el resto de este documento se utilizará únicamente el modelo lineal de memoria. Toda dirección tiene un tamaño de 32 bits yse dispone de un espacio de hasta 4 gigabytes de información almacenados de forma contigua.

Tal y como se ha descrito en la sección 3.4.5, para obtener un mejor rendimiento en el uso de memoria, el bus de datos queconecta al procesador con la memoria tiene un tamaño de 32 bits. Esto quiere decir que el procesador es capaz de manipular 4

Page 76: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

76 / 198

bytes de datos en una sola operación (lectura o escritura) siempre y cuando el acceso sea alineado, es decir, que los datos esténalmacenados a partir de una posición que es múltiplo de cuatro. La figura 4.4 ilustra este mecanismo. El procesador igualmentees capaz de acceder tanto a tamaños de información más pequeños como a datos no alienados, pero dichas operaciones serán máslentas.

Figura 4.4: Acceso alineado a memoria

4.1.2. Registros de propósito general

Los registros son circuitos digitales internos del procesador que se comportan igual que las celdas de memoria, es decir, permitenlas operaciones de lectura y escritura de datos pero a una velocidad mucho mayor, pues no requieren la comunicación con ningúncircuito externo al procesador. Los registros que ofrece un procesador se identifican por su nombre y son susceptibles de serutilizados al escribir programas en ensamblador.

La arquitectura IA-32 ofrece 16 registros básicos para la ejecución de programas: 8 registros de propósito general, 6 registros desegmento, el registro de estado y control, y el registro contador de programa. Los seis registros de segmento no se describen endetalle puesto que se utilizan para acceder a memoria en el modelo segmentado que no se considera en este documento.

Los registros de propósito general son 8 con nombres%eax,%ebx,%ecx,%edx,%esi,%edi,%ebp y%esp. Todos ellos tienenun tamaño de 32 bits y su principal cometido es almacenar datos temporales necesarios para la ejecución de programas. Mientrasla mayor parte de datos e instrucciones se almacenan en la memoria principal, en estos registros se guardan temporalmenteaquellos datos que necesita el procesador más a menudo, de esta forma se obtiene un mejor rendimiento en la ejecución. Porejemplo, si un dato se utiliza varias veces seguidas, en lugar de leerlo de memoria cada vez es mejor almacenarlo al principio enun registro y referirse a esa copia cada vez que sea necesario.

El procesador permite referirse a ciertas porciones de los registros de propósito general con nombres diferentes. Así, se permitemanipular únicamente los 16 bits de menos peso de los ocho registros suprimiendo del nombre la letra ‘e’ del comienzo. Porejemplo, el registro%ax se refiere a los dos bytes de menos peso del registro%eax. Nótese que no es un registro adicional quetenga el procesador, sino la posibilidad de utilizar la mitad menos significativa de un registro. Cuando se realiza una operaciónsobre una porción de un registro, el resto de bits permanece intacto.

Para los primeros cuatro registros, esto es%eax,%ebx,%ecx y%edx se permite manipular los dos bytes de menos peso deforma independiente. Los nombres se obtienen mediante la segunda letra del nombre original añadiendo el sufijo ‘h’ para elde más peso o ‘l’ para el de menos peso. Por tanto, el registro%eax tiene un tamaño de 32 bits, sus 16 bits de menos peso semanipulan mediante el nombre%ax, el byte de menos peso mediante el nombre%al y el segundo de menos peso con%ah. Lafigura 4.5 muestra los ocho registros de propósito general así como los nombres para referirse a las diferentes porciones.

Page 77: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

77 / 198

Figura 4.5: Registros de propósito general

4.1.3. Registro de estado y control

Durante la ejecución de instrucciones existen situaciones especiales que convienen ser reflejadas en un registro para su posibleconsulta. Por ejemplo, si el resultado de una operación aritmética ha producido acarreo, es probable que un programa tenga quetomar medidas especiales. La forma de ofrecer este tipo de funcionalidad consiste en capturar estas condiciones en un registrode estado. El número de bits y condiciones que se almacenan en este registro es diferente en cada arquitectura. Un ejemplo defuncionalidad análoga a esta es el conjunto de luces e indicadores que tiene un equipo de música. Mediante esos indicadoresinforman al usuario de algunas de las condiciones de funcionamiento internas (nivel de audio, filtros encendidos, etc). En elcontexto de un procesador es suficiente almacenar estos valores en un registro e incluir en su lenguaje máquina instruccionespara su manipulación.

Pero aparte de las condiciones de funcionamiento, existe un conjunto de funcionalidades que es preciso activar o desactivar enciertos momentos de la ejecución de un procesador. Continuando con la analogía del equipo de música, este ofrece un conjuntode interruptores o mandos para controlar ciertos aspectos de funcionamiento del dispositivo. Un procesador ofrece también estaposibilidad a través de los denominados bits de control y que suelen almacenarse también en el registro de estado y control. Porejemplo, la arquitectura IA-32 permite que una instrucción sea interrumpida y se pase a ejecutar momentáneamente un conjuntode instrucciones. Mediante un bit de control se permite o prohibe que estas interrupciones se produzcan.

El registro de estado y control de la arquitectura IA-32 se denomina ‘Eflags’ y consta de 32 bits. La figura 4.6 muestra suestructura, en la que se comprueba que de los 32 bits tan sólo 18 de ellos contienen información sobre el estado y control, el restocontienen un valor fijo.

Page 78: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

78 / 198

Figura 4.6: Registro de estado y control

Las condiciones que representan los bits más importantes de este registro son:

Bit de acarreo (CF): Su valor es 1 si una operación aritmética con naturales ha producido acarreo. Este bit se utiliza, por tantopara detectar situaciones de desbordamiento.

Bit de paridad (PF): Su valor es 1 si el byte menos significativo de una operación aritmética contiene un número impar deunos.

Bit de ajuste (AF): Su valor es 1 si se produce acarreo en operaciones aritméticas en la codificación BCD.

Bit de cero (ZF): Su valor es 1 si el resultado de la última operación aritmética ha sido cero.

Bit de signo (SF): Su valor es idéntico al bit más significativo del resultado que corresponde con el bit de signo, cero si espositivo y 1 si es negativo.

Bit de desbordamiento (OF): Su valor es 1 si el entero obtenido como resultado no puede ser representado en complemento a2 con el número de bits utilizado.

Si se pudiese ver la evolución de los valores de bits de estado durante la ejecución de un programa se podría comprobar cómosus valores fluctúan continuamente dependiendo de los resultados aritméticos producidos. El valor de estos bits se mantiene enel registro eflags mientras no se realice otra operación aritmética. El valor de estos bits modifican el comportamiento de unsubconjunto muy relevante de instrucciones del procesador, entre ellas los saltos condicionales.

4.1.4. El registro contador de programa

Desde el instante en que un procesador comienza a funcionar, esto es, cuando el circuito recibe el voltaje necesario, hasta que estevoltaje desaparece, su actividad consiste en ejecutar las instrucciones máquina almacenadas en memoria. El procesador obtieneuna instrucción de memoria, la interpreta, ejecuta y al terminar repite el proceso con la siguiente instrucción.

Page 79: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

79 / 198

Como consecuencia, en todo momento se debe saber dónde está almacenada la siguiente instrucción a ejecutar. Es decir, mientrasen el interior del procesador se interpreta la instrucción recibida, se debe almacenar la dirección de memoria a la que hayque acceder para ejecutar la siguiente instrucción. En la arquitectura IA-32, en el modelo lineal de memoria, esa dirección dememoria consta de 32 bits y se almacena en el registro con nombre%eip (extended instruction pointer). Si la instrucción queestá ejecutando no indica lo contrario, el procesador continua con la instrucción que está almacenada en las siguientes posicionesde memoria. Algunas instrucciones, como por ejemplo las de salto, modifican el contenido de este registro, y por tanto modificanla secuencia de ejecución.

Todo procesador dispone de un registro de estas características y que se conoce generalmente como el ‘contador de programa’ oPC. En el caso de la arquitectura IA-32 , no es posible acceder a%eip de forma explícita, o sea que no se puede leer ni escribirdirectamente un valor. En cambio, sí se puede modificar de forma implícita mediante instrucciones como por ejemplo las de saltoo las de llamadas a subrutina.

La forma que tiene el procesador de cargar la siguiente instrucción a ejecutar consiste en sacar el contenido del registro%eip albus de direcciones de memoria y efectuar una operación de lectura tal y como ilustra la figura 4.7. Cuando dicha operación haterminado, el procesador obtiene el conjunto de bits que codifican la siguiente instrucción a ejecutar.

Figura 4.7: Contador de programa

4.1.5. Otros registros de la arquitectura IA-32

Aparte de los descritos anteriormente, el procesador dispone de registros adicionales para efectuar operaciones especializadas,que aunque no se estudian en detalle, son muy importantes para obtener el mayor rendimiento posible en la ejecución de progra-mas. La arquitectura los agrupa de la siguiente forma:

Ocho registros de 80 bits para almacenar números reales codificados en coma flotante. Por contra, el grupo de registrosdescritos anteriormente se utiliza para operar con números naturales, enteros y caracteres.

Tres registros de 16 bits que almacenan bits de estado, control y etiquetado de números en coma flotante. Se utilizan paracodificar condiciones especiales de sus operaciones.

Un registro de 11 bits que contiene el código de operación de la última instrucción con operandos en coma flotante.

Dos registros de 48 bits con la dirección de memoria de la última instrucción con operandos en coma flotante y la direccióndel último operando en coma flotante obtenido de memoria.

Page 80: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

80 / 198

Ocho registros de 64 bits para la ejecución de instrucciones del tipo MMX. Estas 57 instrucciones están orientadas a laejecución eficiente de aplicaciones multimedia y procesado de señal de audio y vídeo.

Ocho registros de 128 bits para la ejecución de instrucciones de tipo SIMD (Single Instruction Multiple Data).

Tanto las instrucciones de tipo MMX como las de tipo SIMD persiguen una finalidad similar. Tras analizar el tipo de programasque ejecutan estos procesadores, se han identificado ciertas instrucciones que aparecen en aplicaciones de procesado de vídeo enlas que es preciso realizar una única instrucción sobre un conjunto muy grande de datos. Por ejemplo, supóngase que se debesumar una constante a toda una tabla de números. En lugar de ejecutar esta operación con las instrucciones convencionales, esdecir, realizar la suma elemento a elemento, el procesador ofrece la posibilidad de ejecutar esta instrucción sobre todos los datos ala vez. De esta posibilidad se deriva su nombre (SIMD, única instrucción, múltiples datos). Dado que el tamaño de los operandoses mayor que el de las instrucciones convencionales, se requiere un banco de registros especial para ellas.

4.1.6. Estado visible de un programa

De toda la arquitectura IA-32, en adelante se considerará únicamente la parte encargada de ejecutar instrucciones con enteros,naturales y caracteres. No se estudiarán ni las instrucciones ni la arquitectura para manipular números en coma flotante ni lasextensiones MMX y SIMD.

Una vez restringido el ámbito de estudio a este subconjunto, los datos que utiliza un procesador para ejecutar las instruccionesmáquina están almacenados en un conjunto de dispositivos concretos. Se define como el ‘estado visible de un programa’ alconjunto de datos imprescindibles para su ejecución. La forma de decidir qué datos forman parte de este estado es si se considerala situación en la que un programa en ejecución se detiene y se transfiere a otro procesador. ¿Qué datos deben transferirse paraque la ejecución en este nuevo procesador continúe exactamente igual a como procedería en el procesador origen? El estado estácontenido en los siguientes elementos:

La memoria RAM. Es el lugar en el que están almacenados los datos y el código de un programa por lo que su ejecucióndepende de ella.

Los registros de propósito general. En cualquier instante de la ejecución de un programa, estos registros contienen datostemporales que son resultados parciales u operandos a utilizar en el futuro. Por esta razón, estas ocho palabras de 4 bytes cadauna forman parte del estado visible.

Los bits de estado contenidos en el registro eflags puesto que la ejecución de ciertas instrucciones varía dependiendo deestos valores.

El contador de programa. Indica qué instrucción está ejecutando el procesador, y por tanto es parte imprescindible de esteestado.

4.2. Ciclo de ejecución de una instrucción

Se define como el ciclo de ejecución de un procesador a los pasos internos que sigue para ejecutar una instrucción. El númerode pasos y duración de este ciclo varían de procesador a procesador y depende totalmente de su arquitectura. La mayor partede las técnicas utilizadas para obtener un mayor rendimiento en la ejecución de instrucciones están orientadas a modificar laarquitectura para obtener un ciclo de ejecución más rápido.

La complejidad del ciclo de ejecución depende de la arquitectura. La arquitectura IA-32 tiene múltiples ciclos de ejecuciónposible dependiendo del tipo de instrucción a ejecutar. A modo de simplificación se estudia el más representativo de ellos queutilizan las operaciones que manipulan datos enteros. El ciclo de ejecución de estas instrucciones consta de cinco etapas: fetch(F), decodificación inicial (D1), decodificación final (D2), ejecución (E) y escritura de resultados (W). La figura 4.8 muestra lasecuencia de fases en la ejecución de varias instrucciones.

Page 81: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

81 / 198

Figura 4.8: Ciclos de ejecución de varias instrucciones

A continuación se describen las tareas que se realizan en cada una de estas fases.

4.2.1. Fase de fetch

En esta fase el procesador obtiene la siguiente instrucción a ejecutar de memoria. Para ello se carga el contenido del registrocontador de programa%eip en el bus de direcciones y se realiza una operación de lectura. El procesador recibe los primerosbytes de la instrucción y los almacena en el registro de instrucciones (IR) para proceder a su decodificación. Al mismo tiempoque se obtienen los primeros bytes de la instrucción se calcula el siguiente valor para el contador de programa. Este valor todavíano se almacena en%eip puesto que la longitud de la instrucción no se sabe con exactitud hasta que se termina la fase dedecodificación. La figura 4.9 muestra una versión simplificada de los componentes internos del procesador que participan en estafase.

Figura 4.9: Fase de fetch

4.2.2. Fase de decodificación inicial

El proceso de decodificación de una instrucción está dividido en dos fases debido principalmente a que la arquitectura IA-32tiene un formato de instrucción de longitud variable. Durante esta fase los bytes que codifican una instrucción se obtienen deforma gradual pues no se sabe de antemano su tamaño. La decodificación se realiza a partir de los datos obtenidos en la faseanterior y depositados en el registro de instrucciones y se obtiene el número de bytes que ocupa la instrucción y sus componentesbásicos.

Lo primero que se obtiene es el código de operación. Dependiendo del valor recibido se procede a obtener el resto de loselementos de la instrucción con sus respectivos tamaños. Al terminar esta fase ya se sabe con exactitud la operación a realizar yla forma en que obtener sus operandos. El contador de programa ya puede ser actualizado con el valor de la dirección en la quecomienza la siguiente instrucción. La figura 4.10 muestra los componentes que participan en esta fase.

Page 82: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

82 / 198

Figura 4.10: Fase de decodificación inicial

Las instrucciones de la arquitectura IA-32 pueden tener hasta un máximo de dos operandos que a su vez pueden estar almacenadosen múltiples lugares (registros, memoria, la propia instrucción, etc). Una vez terminada esta fase, el procesador ya sabe qué pasosseguir para obtener los operandos y ejecutar el resto de la instrucción pero todavía no ha obtenido ninguno de ellos. La razónpor la que existe esta fase de decodificación previa es por la complejidad del lenguaje máquina. Al tener formato variable existenmultitud de comprobaciones que se deben hacer en la información recibida de memoria para saber de qué instrucción se trata.

4.2.3. Fase de decodificación final

Esta fase se encarga de obtener los operandos que participan en la ejecución de la instrucción y que pueden estar almacenadosen varios lugares: registros, memoria o incluso formar parte de la propia instrucción. En el caso de que un operando esté enmemoria, esta fase necesita ejecutar una operación de lectura de memoria. Previa a esta operación el procesador debe calcular ladirección efectiva del operando, es decir, su posición en memoria. En general, los procesadores ofrecen un número elevado deposibilidades para especificar esta dirección en una instrucción máquina. La figura 4.11 ilustra lo que sucede en esta fase parauna instrucción que contiene dos operandos, el primero de ellos está en un registro y el segundo en memoria. El cálculo de ladirección efectiva puede requerir operaciones aritméticas no triviales.

Figura 4.11: Fase de decodificación final

4.2.4. Fase de ejecución

Una vez obtenidos los operandos, en esta fase se realizan los cálculos aritméticos especificados en la instrucción. La duraciónde esta fase depende del tipo de operación requerida. Por ejemplo, una suma tarda un tiempo mucho más reducido que unamultiplicación o división entera. La duración de esta fase se puede representar o como una fase de duración variable o comomúltiples fases consecutivas de ejecución de duración fija.

Page 83: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

83 / 198

Además del cálculo aritmético, es en esta fase en la que se actualizan los valores de los bits del registro de estado y de controlcon los valores derivados del resultado producido. La figura 4.12 muestra los componentes que participan en esta fase.

Figura 4.12: Fase de ejecución

4.2.5. Fase de escritura de resultados

Una vez terminada la operación aritmético/lógica codificada en la instrucción, el procesador guarda el resultado obtenido enun destino que puede ser igualmente un registro interno o una posición de memoria. La figura 4.13 muestra los elementosinvolucrados en esta fase y las dos posibilidades de escritura.

Figura 4.13: Fase de escritura de resultado

Al terminar esta fase, el procesador tiene en el contador de programa la dirección de memoria en la que está almacenada lasiguiente instrucción. La siguiente fase de fetch comienza la ejecución de una nueva instrucción.

La secuencia de fases descrita anteriormente es una de las múltiples que utiliza el procesador. Existen instrucciones que ejecutanligeras variaciones con respecto a esta secuencia de cinco pasos. Como ejemplo de esta variedad se pueden tomar las instruccionesde coma flotante. La forma en que el procesador opera con números reales aumenta el número de fases hasta ocho. Tras las dosetapas de decodificación se produce un acceso a memoria. Tras la fase de escritura de resultados, este tipo de instrucciones tieneuna fase adicional de notificación de errores. Situaciones tales como el desbordamiento por arriba o por abajo así como otrassituaciones erróneas (ver el capítulo 2) son notificadas mediante excepciones y suelen detener la ejecución del programa. Tal esla importancia de estos errores que el procesador dedica una de sus fases de ejecución a estas tareas. La figura 4.14 muestra elciclo de ejecución para las instrucciones en coma flotante.

Page 84: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

84 / 198

Figura 4.14: Ciclo de ejecución de instrucciones de coma flotante

En este ciclo de ejecución se puede comprobar como las dos primeras fases son idénticas a las instrucciones de aritmética entera.Las flechas en las dos fases de ejecución indican que su duración varía dependiendo de la operación y los operandos involucrados.

4.2.6. Ejecución de una instrucción

Para ilustrar el ciclo de ejecución se analiza a continuación la ejecución detallada de una instrucción concreta del procesador.Supóngase que en la posición de memoria n se encuentra la instrucción INC%eax que tiene el efecto de incrementar o sumar 1al contenido del registro de propósito general%eax y depositar el resultado de nuevo en el mismo registro. Esta instrucción secodifica con un único byte con valor 0x40. El ciclo de ejecución de esta instrucción consta de los siguientes pasos:

1. Fase de fetch: Se obtiene de la posición de memoria n contenida en el contador de programa el byte que codifica lainstrucción. Se calcula el nuevo valor del contador, que en este caso es n + 1 pero todavía no se actualiza.

2. Fase de decodificación inicial: Se detecta que no es preciso obtener más datos de memoria pues con un único byte essuficiente. Se identifica la operación de incremento y que tiene un único operando que es un registro de propósito general.Se actualiza el valor del contador de programa a n + 1.

3. Fase de decodificación final: Se obtienen los operandos de la instrucción que en este caso es el valor almacenado en elregistro%eax.

4. Fase de ejecución: Utilizando la unidad aritmético/lógica se realiza la suma del valor del registro obtenido en la faseanterior y la constante 1. Se actualizan los bits de estado pertinentes en el registro de estado y de control.

5. Fase de escritura de resultado: El resultado obtenido en la fase anterior se escribe de nuevo en el registro%eax.

4.2.7. Ciclo de ejecuciones en procesadores actuales

La descripción anterior supone una simplificación significativa de la estructura real de la arquitectura IA-32 que permite la ejecu-ción de múltiples instrucciones de forma simultánea. La ejecución se realiza mediante una técnica denominada ‘segmentación’(en inglés ‘pipelining’) que se asemeja al esquema de cadena de producción. Al dividir la ejecución de instrucciones en fases,mientras una instrucción está en su fase de ejecución se puede estar decodificando la siguiente y haciendo el fetch de la siguiente.Al circuito que implementa este esquema de ejecución se le denomina ‘pipeline’.

Además de la técnica de segmentación, la arquitectura IA-32 consigue aumentar la velocidad de ejecución mediante la utilizaciónde múltiples flujos de ejecución. Es decir, el procesador no sólo simultanea las diferentes fases del ciclo de ejecución de variasinstrucciones sino que dispone de múltiples pipelines que trabajan en paralelo. A los procesadores con esta característica se lesdenomina ‘superescalares’. La consecuencia más importante de esta técnica es que el orden en que se ejecutan las instruccionespuede verse alterado por el paralelismo creado.

De este paralelismo se deriva gran parte de la complejidad de diseño de estos procesadores. A nivel de un programa en ensambla-dor, el paradigma de ejecución en el que se asume que las instrucciones se ejecutan una tras otra. El procesador por tanto utilizalas técnicas de segmentación y paralelismo para aumentar la velocidad de ejecución pero debe mantener en todo momento laconsistencia con el esquema secuencial. En otras palabras, internamente un procesador puede reorganizar y paralelizar la ejecu-ción de instrucciones todo lo que pueda siempre y cuando los resultados producidos concuerden con la ejecución secuencial deinstrucciones.

En la actualidad, los procesadores más modernos de la arquitectura IA-32 contienen múltiples pipelines especializados en dife-rentes tipos de instrucciones (enteros, coma flotante, saltos, etc.) con lo que se consigue una velocidad de ejecución muy elevada.

Page 85: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

85 / 198

4.3. La pila

Aparte de los componentes de la arquitectura presentados en las secciones anteriores, la mayor parte de procesadores ofrecen lainfraestructura necesaria para manipular una estructura de datos organizada y almacenada en memoria que se denomina ‘la pila’.

La pila es una zona de la memoria sobre la que se pueden escribir y leer datos de forma convencional. Esta zona tiene unaposición especial que se denomina ‘la cima de la pila’. El procesador contiene dos instrucciones de su lenguaje máquina pararealizar las operaciones de ‘apilar’ y ‘desapilar’ datos de la pila. Los datos que se pueden apilar y desapilar, en el caso de laarquitectura IA-32 son siempre de tamaño 4 bytes.

4.3.1. Instrucciones de manejo de la pila

La instrucción para apilar un dato en la pila tiene el formato push dato. Es una instrucción con un único operando quedeposita el dato especificado como parámetro en la cima de la pila. Supóngase que la cima de la pila está en la posición @cima.La instrucción push dato produce el siguiente efecto.

Se resta 4 a la dirección de la cima de la pila, se obtiene, por tanto @cima - 4.

Se escribe el dato de 32 bits dado como único operando en la posición de memoria indicada por @cima - 4 y la direcciónde la cima se asigna a este nuevo valor. El dato que estaba previamente almacenado en esas posiciones se ha perdido.

La figura 4.15 muestra la pila antes y después de ejecutar la instrucción push dato.

Figura 4.15: Efecto de la instrucción push

De la descripción de la instrucción push se deduce que efectúa una operación de escritura en memoria RAM. Si a continuaciónde esta instrucción se ejecuta otra del mismo tipo, el dato se almacena a partir de la cuarta posición de memoria antes del últimovalor depositado en de la pila.

La instrucción pop destino ejecuta el procedimiento complementario al de push dato. Tiene un único operando que, eneste caso, especifica el lugar en el que almacenar el dato que se encuentra en la cima de la pila. Supóngase que la cima de la pilaestá en la posición de memoria @code. La ejecución de la instrucción pop destino tiene el siguiente efecto.

Se lee el dato de 32 bits almacenado en la posición de memoria indicada por la dirección de la cima @cima y se almacena enel lugar especificado como operando de la instrucción.

Page 86: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

86 / 198

Se suma 4 a la dirección de la cima de la pila, se obtiene, por tanto @cima + 4.

La figura 4.16 muestra la pila antes y después de ejecutar la instrucción pop destino.

Figura 4.16: Efecto de la instrucción pop

Nótese que las instrucciones push y pop tienen estructura y efectos complementarios. La instrucción push recibe como ope-rando el dato a depositar, no es preciso especificar el destino pues se deposita automáticamente en la nueva cima. La instrucciónpop, por contra, recibe como parámetro el lugar en el que almacenar el dato obtenido y no es preciso indicar de dónde se obtienepues se lee automáticamente de la cima de la pila. La instrucción push ajusta la cima restando 4 al valor actual, mientras quepop suma 4 a ese valor. Además, una instrucción realiza una operación de lectura en memoria y la otra una operación de escritu-ra. El dato que la instrucción pop lee de la cima de la pila no desaparece de esa posición de memoria, pues lo único que se hacees leer ese valor. Sí es cierto que la cima de la pila ya no apunta a ese dato, pero este sigue almacenado en la misma posición.

Los destinos posibles que se pueden especificar en la instrucción pop dependen del lenguaje máquina del procesador, pero en laarquitectura IA-32 se permite especificar cualquier registro de propósito general de 32 bits como operando de esta instrucción.Por ejemplo, la instrucción pop%edx lee los cuatro bytes almacenados en la cima de la pila, los copia en el registro%edx yajusta la dirección de la cima.

4.3.2. El puntero de pila

Del funcionamiento de las instrucciones push y pop se deduce que en algún lugar del procesador debe estar almacenada ladirección de la cima de la pila y que dicho valor es modificado por ambas instrucciones. En el caso de la arquitectura IA-32, estadirección de memoria está guardada por defecto en el registro de propósito general%esp. Las dos últimas letras del nombre deeste registro corresponden con las iniciales de las palabras stack pointer o ‘apuntador de pila’. La primera consecuencia de estacaracterística del procesador es que, a pesar de que dichos registros están, en principio, disponibles para almacenar valores deforma temporal, el caso de%esp es especial, pues es donde las instrucciones de manipulación de la pila asumen que se encuentrala dirección de la cima. El tamaño de este registro es de 32 bits que coincide con el tamaño de toda dirección de memoria en laarquitectura IA-32.

Si en el instante antes de ejecutar una instrucción push%esp contiene el valor v1, tras su ejecución contendrá el valor v1 - 4.De forma análoga, si antes de ejecutar la instrucción pop%esp contiene el valor v2, tras su ejecución contendrá el valor v2 +4. La figura 4.17 muestra el efecto de la ejecución de dos instrucciones consecutivas sobre la pila tanto en memoria como en losregistros de propósito general.

Page 87: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

87 / 198

Figura 4.17: Ejecución de instrucciones de pila

El que la dirección de la pila esté contenida en un registro de propósito general permite que su contenido sea manipulado comocualquier otro registro. Un programa, por tanto, puede leer y escribir cualquier valor de%esp, tan sólo se debe tener en cuentaque el procesador obtiene de ese registro la dirección de memoria necesaria para ejecutar las instrucciones push y pop.

Supóngase que se ha depositado un cierto dato en la pila mediante la instrucción push y que se encuentra, por tanto en la cima.La instrucción pop deposita ese valor en el lugar especificado pero, ¿es posible ejecutar la instrucción pop sin ningún operando?.En otras palabras, la operación que se quiere ejecutar no es la de copiar el dato de la cima, sino simplemente corregir el valorde la cima al igual que haría pop pero sin depositar el dato en ningún lugar. La instrucción pop, por definición, debe incluir unúnico operando, con lo que no se puede utilizar para hacer esta operación.

La solución se deriva del hecho de que%esp es un registro de propósito general y de que todos los datos leídos o extraídos de lapila son de tamaño 4 bytes. Para corregir el valor de la cima de la pila tal y como hace pop pero sin depositar su valor en destinoalguno es suficiente con sumar 4 al valor de%esp. La instrucción ADD $4,%esp produce exactamente ese efecto. El primeroperando es la constante a sumar, y el segundo es a la vez el otro sumando y el lugar donde dejar el resultado. Esta instrucciónpor tanto asigna a%esp su valor incrementado en cuatro unidades. El efecto que esta instrucción tiene sobre la pila es el deseado.La siguiente instrucción asume que la cima está en la nueva posición contenida en%esp.

4.3.3. Valores iniciales del puntero de pila

Todo programa en ensamblador comienza ejecutar con un valor en el registro%esp que apunta a la cima de la pila previamentepreparada. Los programas, por tanto, no deben realizar operación alguna para inicializar la pila ni para reservar su espacio. Estatarea la lleva a cabo, antes de que comience la ejecución, el sistema operativo.

El sistema operativo es un programa que se encarga de realizar las tareas de administración de todos los dispositivos y recursosdisponibles en el equipo. Entre ellas se encuentra la de permitir la ejecución de programas en ensamblador. Todo programaantes de comenzar a ejecutar su primera instrucción tiene una zona de memoria reservada para la pila y su puntero a la cimacorrectamente inicializado.

Pero la memoria de un equipo es limitada, y por tanto, la pila ocupa un lugar en memoria también limitado. ¿Qué sucede si seintenta acceder a posiciones de memoria fuera de este límite? Esta situación puede ser provocada al menos por dos situaciones:se deposita un dato mediante la instrucción push cuando todo el espacio reservado para la pila ya está ocupado o se intentaobtener un dato de la pila cuando esta no contiene dato alguno.

Supóngase que la pila está almacenada en la zona de memoria que va desde la dirección p hasta la dirección q (ambas inclusive)y p < q. ¿Qué valores contiene el registro%esp cuando la pila está llena y cuando está vacía? Si la pila está llena entonces la cimaestá en la posición de memoria con valor más bajo posible, es decir cima = p. Si en estas condiciones se ejecuta una instrucciónpush el procesador detiene la ejecución del programa de forma abrupta.

Page 88: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

88 / 198

Si la pila está vacía quiere decir que no se ha introducido dato alguno en ella y por tanto si se ejecutase la instrucción push sedepositaría el primer dato. Por tanto, la cima de la pila vacía debe estar en la posición q + 1 para que el dato del primer pushse almacene correctamente. La figura 4.18 muestra los valores de la cima para las dos condiciones descritas.

Figura 4.18: Valores de la cima para la pila vacía y llena

4.4. Ejercicios

1. La instrucción ADD $128,%eax suma la constante 128 al contenido del registro%eax y deposita el resultado de nuevoen dicho registro. Describir los pasos que sigue el procesador en las cinco fases de ejecución de esta instrucción.

2. ¿Cuántos registros cambian de contenido tras ejecutar la instrucción push%eax?

3. ¿Cuántos registros, como máximo, cambian de contenido tras ejecutar la instrucción pop%eax?

4. ¿Cuántos registros contienen datos diferentes al ejecutar la instrucción push%eax seguida de la instrucción pop%eax?

5. ¿Cuántas posiciones de memoria han modificado su valor, como máximo, tras ejecutar las dos instrucciones de la preguntaanterior?

6. La instrucción pop%edx no ha modificado el contenido del registro%edx ¿Cómo es esto posible?

7. ¿Qué efecto se produce en la pila si mediante una instrucción se suma 4 al registro%esp? ¿Y si se resta 4?

8. ¿Qué secuencia de cuatro instrucciones de pila se pueden ejecutar para intercambiar los valores de dos registros?

9. ¿Cómo se define el estado visible de un programa?. ¿En qué cuatro elementos está contenido dicho estado en la versiónsimplificada del procesador?

10. Escribir la secuencia de instrucciones en ensamblador cuya ejecución sea equivalente a ejecutar la instrucción push %eax.Explicar la solución propuesta.

11. Escribir la secuencia de instrucciones en ensablador cuya ejecución sea equivalente a ejecutar la instrucción pop %eax.Explicar la solución propuesta.

Page 89: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

89 / 198

Capítulo 5

Juego de instrucciones

A la definición detallada del conjunto de instrucciones que es capaz de ejecutar un procesador se le denomina su ‘juego deinstrucciones’ (o, en ingles, Instruction Set Architecture). Esta definición es la que determina de forma inequívoca el efecto decada instrucción sobre las diferentes partes de la arquitectura del procesador. El número de instrucciones máquina puede llegar aser muy elevado debido a que la misma instrucción (por ejemplo, la de suma) se puede ejecutar sobre diferentes tipos de datos ycon diferentes variantes (números naturales, enteros, etc.)

5.1. Tipos de juegos de instrucciones

La decisión de qué instrucciones es capaz de ejecutar un procesador es una de las más importantes y en buena medida esdeterminante en el rendimiento a la hora de ejecutar programas. Además, el juego de instrucciones y la arquitectura del procesadorestán interrelacionados. Por ejemplo, generalmente todas las instrucciones del lenguaje máquina de un procesador pueden utilizarlos registros de propósito general, por lo que su número tiene un efecto directo en la codificación de instrucciones.

La decisión de qué instrucciones incluir en un procesador está también influenciada por la complejidad que requiere su diseño. Siuna instrucción realiza una operación muy compleja, el diseño de los componentes digitales necesarios para su ejecución puederesultar demasiado complejo.

Considérese el siguiente ejemplo. ¿Debe un procesador incluir en su lenguaje máquina una instrucción que dado un número realy los coeficientes de un polinomio de segundo grado obtenga su valor? Supóngase que esta instrucción se llama EPSG (evaluarpolinomio de segundo grado). Un posible formato de esta instrucción se muestra en el ejemplo 5.1.

Ejemplo 5.1 Formato de la instrucción EPSG

EPSG a, b, c, n, dest

La instrucción realiza los cálculos con los cuatro primeros parámetros tal y como se muestra en la ecuación 5.1 y almacena elresultado en el lugar especificado por el parámetro dest.

f (n) = an2 +bn+ c

EQUATION 5.1: Polinomio de segundo grado para el valor n

La ecuación 5.1 especifica las operaciones a realizar para evaluar el polinomio, en este caso suma y multiplicación. Un procesadorque no disponga de la instrucción máquina EPSG puede obtener el mismo resultado pero ejecutando múltiples instrucciones.

El compromiso a explorar, por tanto, a la hora de decidir si incluir una instrucción en el lenguaje máquina de un procesador estáentre la complejidad de las instrucciones y la complejidad del lenguaje. Si un procesador soporta la ejecución de la instrucción

Page 90: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

90 / 198

EPSG, requiere una estructura interna más compleja, pues debe manipular sus múltiples operandos y ejecutar las operacionesnecesarias. En cambio, si un procesador ofrece la posibilidad de realizar multiplicaciones y sumas, la evaluación del polinomioes igualmente posible aunque mediante la ejecución de múltiples instrucciones, con lo que no será una ejecución tan rápida. Engeneral, un lenguaje máquina con instrucciones sofisticadas requiere una implementación más compleja del procesador. De igualforma, un lenguaje máquina sencillo (pero que ofrezca las operaciones mínimas para poder realizar todo tipo de cálculos) permiteun diseño más simple.

De este compromiso se ha derivado a lo largo de los años una división de los procesadores en dos categorías dependiendo de lafilosofía utilizada para el diseño de su lenguaje máquina:

Los procesadores que ejecutan un conjunto numeroso de instrucciones y algunas de ellas de cierta complejidad se les denominade tipo CISC (Complex Instruction Set Computer). Las instrucciones más complejas son las que requieren múltiples cálculosy accesos a memoria para lectura/escritura de operandos y resultados.

El ejemplo más representativo de esta filosofía es la arquitectura IA-32. Su lenguaje máquina consta de instrucciones capacesde realizar operaciones complejas. Otro ejemplo de procesador CISC es el Motorola 68000, que aunque en la actualidad hadejado paso a otro tipo de procesadores pero que está todavía presente en ciertos productos electrónicos y ha sido la inspiraciónde múltiples modelos actuales.

Los procesadores que ejecutan un conjunto reducido de instrucciones simples se denominan de tipo RISC (Reduced InstructionSet Computer). El número de posibles instrucciones es muy pequeño, pero a cambio, el diseño del procesador se simplifica yse consiguen tiempos de ejecución muy reducidos con el consiguiente efecto en el rendimiento total del sistema.

Ejemplos de algunos procesadores diseñados con esta filosofía son:

• MIPS (Microprocessor without interlocked pipeline stages): utilizado en encaminadores, consola Nintendo 64, PlayStationy PlayStation 2 y PlayStation portátil (PSP).

• ARM: presente en ordenadores portátiles, cámaras digitales, teléfonos móviles, televisiones, iPod, etc.• SPARC (Scalable Processor Architecture): línea de procesadores de la empresa Sun Microsystems. Se utilizan principal-

mente para servidores de alto rendimiento.• PowerPC: arquitectura inicialmente creada por el consorcio Apple-IBM-Motorola para ordenadores personales que está

presente en equipos tales como servidores, encaminadores, es la base para el procesador Cell presente en la PlayStation 3,XBox 360, etc.

En la actualidad, esta división entre procesadores CISC y RISC se ha empezado a difuminar. La propia arquitectura IA-32decodifica las instrucciones de su lenguaje máquina y las traduce a una secuencia de instrucciones más simples denominadas‘microinstrucciones’. Se puede considerar, por tanto, que el lenguaje formado por estas microinstrucciones tiene una estructuracercana a la categoría RISC, mientras que el conjunto de instrucciones máquina es de tipo CISC.

Otra importante decisión a la hora de diseñar un lenguaje máquina es el formato en el que se van a codificar las instrucciones.Ateniendo a este criterio los procesadores se pueden dividir en:

Formato de longitud fija. Todas las instrucciones máquina se codifican con igual número de bits. De esta característica sederivan múltiples limitaciones del lenguaje. El número de operandos de una instrucción no puede ser muy elevado, pues todosellos deben ser codificados con un conjunto de bits. Al igual que sucede con los operandos, el tipo de operación debe sertambién codificado, y por tanto este tipo de lenguajes no pueden tener un número muy elevado de instrucciones.

Como contrapartida, un formato de instrucción fijo se traduce en una fase de decodificación más simple. El procesador obtienede memoria un número fijo de bits en los que sabe de antemano que está contenida la instrucción entera. Los operandosgeneralmente se encuentran en posiciones fijas de la instrucción, con lo que su acceso se simplifica enormemente.

El procesador PowerPC es un ejemplo de procesador con formato fijo de instrucción. Todas ellas se codifican con 32 bits. Engeneral, los procesadores de tipo RISC optan por una codificación con formato de longitud fija.

Formato de longitud variable. Las instrucciones máquina se codifican con diferente longitud. La principal consecuencia es quela complejidad de una instrucción puede ser arbitraria. En este tipo de lenguaje máquina se puede incluir un número elevadode instrucciones.

El principal inconveniente es la decodificación de la instrucción pues su tamaño sólo se sabe tras analizar los primeros bytescon lo que identificar una instrucción y sus operandos es más complejo.

Los procesadores con arquitectura IA-32 son un ejemplo de procesadores con formato variable de instrucciones. Dicho formatose estudia en mayor detalle en las siguientes secciones.

Page 91: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

91 / 198

5.2. Formato de instrucciones máquina de la arquitectura IA-32

La arquitectura IA-32 codifica sus instrucciones máquina con un formato de longitud variable. Toda instrucción tiene una longitudentre 1 y 16 bytes. La figura 5.1 ilustra las diferentes partes de las que puede constar una instrucción así como su tamaño en bytes.

Figura 5.1: Formato de Instrucción

Las instrucciones comienzan por un prefijo de hasta cuatro bytes, seguido de uno o dos bytes que codifican la operación, un bytede codificación de acceso a operandos, un byte denominado escala-base-índice (scale-base-index), un desplazamiento de hastacuatro bytes, y finalmente un operando inmediato de hasta cuatro bytes. Excepto los bytes que codifican la operación, el resto decomponentes son todos opcionales, es decir, su presencia depende del tipo de operación.

Los prefijos son bytes que modifican la ejecución normal de una instrucción de acuerdo a unas propiedades predefinidas. Elprocesador agrupa estos prefijos en cuatro categorías y se pueden incluir hasta un máximo de uno por categoría. Por ejemplo, elprefijo LOCK hace que mientras se ejecuta la instrucción el procesador tiene acceso en exclusiva a cualquier dispositivo que seacompartido. Este prefijo se utiliza en sistemas en los que se comparte memoria entre múltiples procesadores.

El código de operación codifica sólo el tipo de operación a realizar. Su tamaño puede ser de hasta 2 bytes y en ciertas instruccionesparte de este código se almacena en el byte siguiente denominado ModR/M. Este byte se utiliza en aquellas instrucciones cuyoprimer operando está almacenado en memoria y sus ocho bits están divididos en tres grupos o campos tal y como ilustra la figura5.2 y que almacenan los siguientes datos:

Figura 5.2: Byte ModR/M de las instrucciones de la arquitectura IA-32

El campo Mod combinado con el campo R/M codifica uno de los 8 posibles registros de propósito general, o uno de los 24posibles modos de direccionamiento.

El campo Reg/Opcode codifica uno de los ocho posibles registros de propósito general. En algunas instrucciones estos tresbits forman parte del código de operación.

El campo R/M codifica o uno de los ocho posibles registros de propósito general, o combinado con el campo Mod uno de los24 posibles modos de direccionamiento.

Algunas combinaciones de valores en el byte ModR/M requieren información adicional que se codifica en el byte SIB cuyaestructura se muestra en la figura 5.3.

Page 92: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

92 / 198

Figura 5.3: Byte SIB de las instrucciones de la arquitectura IA-32

Algunos de los modos de direccionamiento ofrecidos por el procesador requieren un factor de escala por el que multiplicarun registro denominado índice, y un registro denominado base. Estos tres operandos se codifican en el byte SIB con los bitsindicados en cada uno de sus campos. Los campos que codifican el registro base y el índice tienen ambos un tamaño de 3 bits, loque concuerda con el número de registros de propósito general de los que dispone el procesador. El factor de escala se codificaúnicamente con 2 bits, con lo que sólo se pueden codificar 4 posibles valores.

El campo denominado ‘desplazamiento’ es opcional, codifica un número de 1, 2 o 4 bytes y se utiliza para calcular la direcciónde un operando almacenado en memoria. Finalmente, el campo denominado ‘inmediato’ (también opcional) tiene un tamaño de1, 2 o 4 bytes y codifica los valores constantes en una instrucción.

La figura 5.4 muestra un ejemplo de como se codifica la instrucción ADDL $4, 14(%eax,%ebx, 8) que suma la constante4 a un operando de 32 bits almacenado en memoria a partir de la dirección cuya expresión es 14 +%eax + (%ebx * 8) con 5bytes con valores 0x8344D80E04.

Figura 5.4: Codificación de una instrucción ensamblador

En este caso, el código de operación está contenido en los primeros 8 bits (valor 0x83) y los 3 bits del campo Reg/Opcode delbyte ModR/M y codifica la instrucción de suma de un valor constante de 8 bits a un valor de 32 bits almacenado en memoria.

Los valores 01 y 100 en los campos Mod y R/M del byte ModR/M respectivamente indican que la instrucción contiene en elbyte SIB los datos que precisa el modo de direccionamiento para acceder al segundo operando así como la dirección en la que sealmacena el resultado.

Los campos del byte SIB contienen los valores 11, 011 y 000 que codifican respectivamente el factor de escala 8, el registroíndice%ebx y el registro base%eax así como el tamaño del desplazamiento que es un byte. La instrucción concluye con un byteque codifica el desplazamiento, seguido de un byte que codifica la constante a utilizar como primer operando.

5.3. El lenguaje ensamblador

Para escribir programas que puedan ser ejecutados por un procesador, todas las instrucciones y datos se deben codificar mediantesecuencias de ceros y unos. Estas secuencias son el único formato que entiende el procesador, pero escribir programas enteros eneste formato es, aunque posible, extremadamente laborioso.

Page 93: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

93 / 198

Una solución a este problema consiste en definir un lenguaje que contenga las mismas instrucciones, operandos y formatos queel lenguaje máquina, pero en lugar de utilizar dígitos binarios, utilizar letras y números que lo hagan más inteligible para elprogramador. A este lenguaje se le conoce con el nombre de lenguaje ensamblador.

El lenguaje ensamblador, por tanto, se puede definir como una representación alfanumérica de las instrucciones que formanparte del lenguaje máquina de un procesador. Tal y como se ha mostrado en la sección 5.2, la traducción de la representaciónalfanumérica de una instrucción a su representación binaria consiste en aplicar un proceso de traducción sistemático.

Considérese de nuevo la instrucción de lenguaje ensamblador utilizada en la figura 5.4, ADDL $4, 14(%eax,%ebx, 8).Una segunda forma de escribir esta instrucción puede ser ADDL 14[%eax,%ebx * 8], 4. En este nuevo formato se hancambiado el orden de los operandos así como la sintaxis utilizada. Cualquiera de las dos notaciones es válida siempre y cuandose disponga del programa que pueda traducirlo a su codificación en binario entendida por el procesador (5 bytes con valores0x8344D80E04).

5.3.1. Formato de instrucción ensamblador

El lenguaje ensamblador que se describe a continuación sigue la sintaxis comúnmente conocida con el nombre de ‘AT&T’ y susprincipales características son que los operandos destino se escriben en último lugar en las instrucciones, los registros se escribencon el prefijo% y las constantes con el prefijo $.

Una sintaxis alternativa utilizada por otros compiladores es la conocida con el nombre de ‘Intel’. En ella, los operandos destinose escriben los primeros en una instrucción, y los registros y constantes no se escriben con prefijo alguno.

En principio es el programa ensamblador quien estipula la forma en la que se deben escribir las instrucciones. Por tal motivo, esposible que existan diferentes ensambladores con diferentes definiciones de su lenguaje, pero que produzcan el mismo lenguajemáquina. Existen también ensambladores capaces de procesar programas escritos en más de un formato, el programa gcc, incluidocon el sistema operativo Linux es uno de ellos. En adelante se utilizará únicamente la sintaxis ‘AT&T’.

Las instrucciones del lenguaje máquina de la arquitectura IA-32 pueden tener uno de los tres siguientes formatos:

Operación. Las instrucciones con este formato no precisan ningún operando, suelen ser fijos y por tanto se incluyen deforma implícita. Por ejemplo, la instrucción RET retorna de una llamada a una subrutina.

Operación Operando. Estas instrucciones incluyen únicamente un operando. Algunas de ellas pueden referirse de maneraimplícita a operandos auxiliares. Un ejemplo de este formato es la instrucción INC%eax que incrementa en uno el valor desu único operando.

Operación Operando1, Operando2. Un ejemplo de este tipo de instrucciones es ADD $0x10,%eax que toma laconstante 0x10 y el contenido del registro%eax, realiza la suma y deposita el resultado en este mismo registro. Como reglageneral, cuando una operación requiere tres operandos, dos fuentes y un destino (por ejemplo, una suma), el segundo operandodesempeña siempre las funciones de fuente y destino y por tanto se pierde su valor inicial.

Algunas de las instrucciones del procesador tienen un formato diferente a estos tres, pero serán tratadas como casos excepciona-les. El ejemplo 5.2 muestra instrucciones de los tres tipos descritos anteriormente escritas en lenguaje ensamblador.

Ejemplo 5.2 Instrucciones del lenguaje ensamblador

push (%ecx)push 4(%ecx)push $msgcall printfadd $12, %esp

pop %edxpop %ecxpop %eaxret

Page 94: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

94 / 198

5.3.2. Descripción detallada de las instrucciones

Para escribir programas en lenguaje ensamblador se necesita una descripción detallada de todas y cada una de sus instrucciones.Dicha descripción debe incluir todos los formatos de operandos que admite, así como el efecto que tiene su ejecución en elprocesador y los datos. Esta información se incluye en los denominados manuales de programación y acompañan a cualquierprocesador.

En el caso de la arquitectura IA-32, su descripción detallada, el lenguaje máquina y funcionamiento se incluye en el documentode poco más de 2000 páginas que lleva por título IA-32 Intel Architecture Software Developer’s Manual y cuyo contenido estádividido en los siguientes tres volúmenes:

Volumen 1. Arquitectura básica (Basic Architecture): describe la arquitectura básica del procesador así como su entorno deprogramación.

Volumen 2. Catálogo del juego de instrucciones (Instruction Set Reference): describe cada una de las instrucciones del proce-sador y su codificación.

Volumen 3. Guía para la programación de sistemas (System Programming Guide): describe el soporte que ofrece esta arqui-tectura al sistema operativo en aspectos tales como gestión de memoria, protección, gestión de tareas, interrupciones, etc.

El ejemplo 5.3 muestra la definición de la instrucción de suma de enteros que forma parte del lenguaje máquina de la arquitecturaIA-32 tal y como consta en su manual.

Ejemplo 5.3 Descripción de la instrucción de suma de enteros en la arquitectura IA-32

ADD--AddOpcode Instruction DescriptionOpcode Instruction Description04 ib ADD AL,imm8 Add imm8 to AL05 iw ADD AX,imm16 Add imm16 to AX05 id ADD EAX,imm32 Add imm32 to EAX80 /0 ib ADD r/m8,imm8 Add imm8 to r/m881 /0 iw ADD r/m16,imm16 Add imm16 to r/m1681 /0 id ADD r/m32,imm32 Add imm32 to r/m3283 /0 ib ADD r/m16,imm8 Add sign-extended imm8 to r/m1683 /0 ib ADD r/m32,imm8 Add sign-extended imm8 to r/m3200 /r ADD r/m8,r8 Add r8 to r/m801 /r ADD r/m16,r16 Add r16 to r/m1601 /r ADD r/m32,r32 Add r32 to r/m3202 /r ADD r8,r/m8 Add r/m8 to r803 /r ADD r16,r/m16 Add r/m16 to r1603 /r ADD r32,r/m32 Add r/m32 to r32

DescriptionAdds the first operand (destination operand) and the second operand (source operand) and stores the result in thedestination operand. The destination operand can be a register or a memory location; the source operand can be animmediate, a register, or a memory location. (However, two memory operands cannot be used in one instruction.) Whenan immediate value is used as an operand, it is sign-extended to the length of the destination operand format. The ADDinstruction performs integer addition. It evaluates the result for both signed and unsigned integer operands and sets the OFand CF flags to indicate a carry (overflow) in the signed or unsigned result, respectively. The SF flag indicates the sign ofthe signed result. This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.OperationDEST← DEST + SRCFlags AffectedThe OF, SF, ZF, AF, CF, and PF flags are set according to the result.

Page 95: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

95 / 198

La parte superior incluye las diferentes versiones de suma de enteros que soporta el procesador dependiendo de los tipos deoperandos. La primera columna muestra los códigos de operación para cada una de las versiones y la segunda columna muestrala estructura en lenguaje ensamblador de cada una de ellas. La sintaxis utilizada en este documento es de tipo Intel (ver la sección5.3.1), por tanto, el operando destino es el primero que se escribe.

La codificación de la instrucción ADD $4, 14(%eax,%ebx, 8) utilizada en el figura 5.4 coincide con la mostrada por estatabla en la octava fila ADD r/m32, imm8, o en otras palabras, la suma de una constante de ocho bits (imm8) a un registro oun dato en memoria (en el ejemplo, un dato en memoria).

En el código de operación, los símbolos ‘ib’, ‘iw’ e ‘id’ significan respectivamente una constante de 8, 16 o 32 bits. El símbolo‘\r’ representa cualquiera de los registros de propósito general del procesador. En la segunda y tercera columna el prefijo ‘imm’seguido de un número representa una constante del tamaño en bits indicado por el número. El prefijo ‘r/m’ seguido de un númerosignifica que el operando es o un registro o un dato en memoria del tamaño del número indicado.

El documento continua con una descripción de palabra de la operación que realiza la instrucción. Se aclara que uno de losoperandos es fuente y destino a la vez, y que no es posible sumar dos operandos que estén ambos en memoria.

La siguiente sección es una descripción funcional de la operación y se utiliza como resumen formal de la descripción textual quele precede. Algunas instrucciones, debido a su complejidad, son más fácilmente descritas mediante esta notación que mediantetexto. Finalmente se mencionan aquellos bits de la palabra de estado del procesador que se modifican al ejecutar una de estasinstrucciones.

5.3.3. Tipos de operandos

Los operandos que utilizan las instrucciones de la arquitectura IA-32 se dividen en las siguientes categorías:

Constantes. El valor debe ir precedido del símbolo ‘$’. Se pueden especificar valores numéricos y cualquier letra o símbolomanipulable por el procesador. Las constantes numéricas se pueden escribir en base hexadecimal si se antepone el prefijo ‘0x’,en base 8 (u octal) si se antepone el prefijo ‘0’, o en binario si se antepone el prefijo ‘0b’. Una constante numérica sin prefijose considera escrita en base 10, por ejemplo: $0xFF23A013, $0763, 0b00101001, $255.

Las constantes que representan letras deben ir precedidas por la comilla simple ’. Por ejemplo, $’A representa la constantenumérica que codifica el valor de la letra a mayúscula.

Registro de propósito general. El nombre del registro contiene el prefijo%. Se pueden utilizar cualquiera de los ocho registrosde propósito general así como sus diferentes porciones (ver la sección 4.1.2), por ejemplo:%eax,%dh,%esp,%bp.

Dirección de memoria. El operando está almacenado a partir de la dirección de memoria dada en la instrucción. Se permiteun amplio catálogo de formas para especificar la dirección de los operandos denominados ‘modos de direccionamiento’ y sedescriben de forma detallada en el capítulo 7.

Operando implícito. No constan pero la instrucción hace uso de ellos. Por ejemplo, la instrucción PUSH deposita el únicooperando dado en la cima de la pila. La instrucción tiene como operando implícito el registro%esp que contiene la direcciónde memoria en la que está almacenado el dato de la cima y se le resta la constante 4 al final de la operación.

La presencia o ausencia de operandos implícitos está contenida en la descripción detallada de las instrucciones máquina.

En la arquitectura IA-32 no todas las combinaciones posibles de tipos de operandos se pueden dar en todas las instrucciones. Laarquitectura impone la restricción de que no se permite la ejecución de una instrucción con dos operandos explícitos que esténalmacenados ambos en memoria. Además, no todas las combinaciones de instrucciones con tipos de operandos tienen sentido.La Tabla 5.1 muestra ejemplos de instrucciones en lenguaje ensamblador correctas e incorrectas.

5.3.4. El sufijo de tamaño

De los tipos de operandos presentados en la sección anterior, no todos tienen definido el tamaño de todos sus componentes. Taly como se ha visto en el capítulo 2, cuando se procesan datos es preciso saber el tamaño utilizado para su codificación.

Considérese la instrucción utilizada como último ejemplo en la Tabla 5.1, MOV $-4, contador. A primera vista, la instruc-ción puede parecer correcta, pues se mueve una constante a una dirección de memoria representada, en este caso, por el símbolocontador. El primer operando, sin embargo, puede ser representado por un número arbitrario de bits. Lo mismo sucede con

Page 96: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

96 / 198

Instrucción CorrectaPUSH $4 Sí

POP $0b11011101No. El operando de esta instrucción es el destino en el quealmacenar el dato en la cima de la pila, y por tanto, nopuede ser una constante.

MOV $-4, %eax Sí. Primer operando es de tipo constante y el segundo detipo registro.

MOV %eax, $0x11011110 No. El segundo operando es el destino de la operación, yno puede ser una constante.

MOV %eax, contador Sí. El segundo operando representa una dirección dememoria.

MOV $’A, %eax Sí. ¿Qué tamaño de datos se está moviendo en estainstrucción a%eax?

MOV $65, %eax Sí. Esta instrucción tiene una codificación idéntica a laanterior.

MOV contador, resultado No. Instrucción con dos operandos, y ambos son de tipodirección de memoria.

MOV $-4, contador ¿Qué tamaño de datos se transfiere a memoria?

Tabla 5.1: Instrucciones con diferentes tipos de operandos

el segundo operando, pues al ser una dirección de memoria, lo único que se puede asegurar es que se utilizarán tantos bytes dememoria como sea preciso.

Como conclusión, la instrucción MOV $-4, contador a pesar de tener un formato correcto, es ambigua. El mismo formatopuede representar las instrucciones que almacena la constante -4 representada por un número variable de bytes en la direcciónindicada por contador. La arquitectura IA-32 sólo permite 3 tamaños para sus operandos: 1 byte, 2 bytes (un word), o 4bytes (un doubleword, ver la Tabla 4.1). Por tanto, la instrucción MOV $-4, contador, puede ser interpretada de tres formasdiferentes dependiendo del tamaño con el que se representa la constante y el número de bytes utilizados para almacenar su valoren memoria (ambos deben ser el mismo número, 1, 2 o 4).

Para solventar este problema, el lenguaje ensamblador permite la utilización de un sufijo en el código de instrucción que indicael tamaño de los operandos utilizados. Este sufijo es la letra ‘B’ para operandos de 1 byte, ‘W’ para operandos de 2 bytes (unword), y ‘L’ para operandos de 4 bytes (un doubleword).

Por tanto, si se quiere codificar la instrucción que almacena la constante -4 representada por 32 bits en la dirección indicada porcontador se debe escribir MOVL $-4, contador.

De todas las instrucciones posibles sólo algunas de ellas son ambiguas. Si alguno de los operandos es un registro, el tamaño deloperando queda fijado por el tamaño del registro. La ambigüedad aparece cuando ninguno de los operandos es un registro, y portanto no es posible deducir el tamaño. Se permite el uso del sufijo de tamaño en una instrucción que no lo requiera, siempre ycuando esté en consonancia con el tamaño de los operandos. La Tabla 5.2 muestra ejemplos de utilización del sufijo de tamaño.

5.4. Instrucciones más representativas de la arquitectura IA-32

A continuación se describe el subconjunto de instrucciones de la arquitectura IA-32 necesario para poder codificar tareas básicasde programación y manipulación de datos de tipo entero y strings. La descripción del lenguaje máquina completo se puedeencontrar en la documentación facilitada por el fabricante. Para simplificar su estudio, las instrucciones se dividen en categorías.Una descripción detallada de cada una de ellas se puede encontrar en el apéndice A.

Page 97: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

97 / 198

Instrucción Comentario

PUSH $4No es preciso el sufijo, los operandos de la pila son siemprede 32 bits.

PUSHL $0b11011101 El sufijo es redundante y concuerda con el tamaño deloperando.

MOVB $-4, contadorEl sufijo es imprescindible porque la instrucción almacenaun único byte que codifica el número -4 en complemento ados en la posición de memoria indicada por contador.

MOV $-4, %axNo es preciso el sufijo porque la presencia deloperando%ax hace que la constante se represente con 16bits.

MOVL %eax, contadorLa presencia del registro%eax hace que el operando seconsidere de 32 bits, y por tanto el sufijo es redundantepero correcto.

MOVB $’A, %eax

Esta instrucción es incorrecta porque contiene un error desintaxis. El sufijo indica tamaño de 1 byte y el segundooperando indica 4 bytes. El sufijo es innecesario y lainstrucción transfiere el número que codifica la constante$’A como número de 32 bits.

INCL contadorLa instrucción incrementa el valor de su único operandoque está almacenado en memoria con lo que la ausencia desufijo la haría ambigua.

Tabla 5.2: Instrucciones con sufijos de tamaño

5.4.1. Instrucciones de transferencia de datos

En esta categoría se incluyen las instrucciones que permiten la transferencia de datos entre registros y memoria tales como MOV,PUSH, POP y XCHG.

La instrucción MOV recibe dos operandos y transfiere el dato indicado por el primer operando al lugar indicado por el segundo.Dada la restricción que impone el procesador de que en una instrucción con dos operandos no pueden estar ambos en memoria,si se quiere transferir datos de un lugar de memoria a otro, se deben utilizar dos instrucciones y utilizar un registro de propósitogeneral.

Las instrucciones PUSH y POP también transfieren datos, aunque en este caso, uno de los operandos es implícito y se refierea la cima de la pila. La instrucción PUSH necesita como operando el dato a colocar en la cima de la pila mientras que lainstrucción POP requiere un único operando para indicar el lugar en el que depositar el dato contenido en la cima de la pila.Ambas instrucciones modifican el registro%esp que contiene la dirección de la cima de la pila (tal y como se ha descrito en lasección 4.3).

Estas dos instrucciones aceptan como operando una posición de memoria, por ejemplo PUSH contador. El procesador cargaen la pila el dato en memoria en la posición con nombre contador. En este caso, a pesar de que la transferencia se estárealizando de memoria a memoria, la arquitectura sí permite la operación. La restricción de dos operandos en memoria aplicaúnicamente a aquellas instrucción con dos operandos explícitos.

La instrucción XCHG (del inglés exchange) consta de dos operandos e intercambia sus valores por lo que modifica los operandos(a no ser que tengan idéntico valor). No se permite que los operandos estén ambos en memoria.

La Tabla 5.3 muestra ejemplos correctos e incorrectos de la utilización de este tipo de instrucciones. Se asume que los símboloscontador1 y contador2 se refieren a operandos en memoria.

5.4.2. Instrucciones aritméticas

En este grupo se incluyen aquellas instrucciones que realizan operaciones aritméticas sencillas con números enteros y naturalestales como la suma, resta, incremento, decremento, multiplicación y división.

Page 98: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

98 / 198

Instrucción Comentario

MOV $4, %al Almacena el valor 4 en el registro de 8 bits%al.

MOV contador1, %esiAlmacena los cuatro bytes que se encuentran en memoria apartir de la posición que representa contador1 en elregistro%esi.

MOV $4, contador1 Instrucción ambigua, pues no se especifica el tamaño dedatos en ninguno de los dos operandos.

MOVL contador, $4Instrucción incorrecta. El segundo operando es el destino alque mover el primer operando, por lo tanto, no puede serde tipo constante.

MOV %al, %ecxInstrucción incorrecta. El tamaño de los dos operandos esinconsistente. El primero es un registro de 8 bits, y elsegundo es de 32.

PUSH $4 Instrucción correcta. Almacena el valor 4, codificado con32 bits en la cima de la pila. No precisa sufijo de tamaño.

POP $4Instrucción incorrecta. El operando indica el lugar en elque almacenar el contenido de la cima de la pila, por tanto,no puede ser un valor constante.

XCHG %eax, %ebx Instrucción correcta.

XCHG %eax, contador1 Instrucción correcta.

XCHG $4, %eaxInstrucción incorrecta. Se intercambian los contenidos delos dos operandos, por lo que ninguno de ellos puede seruna constante.

XCHG contador1, contador2Instrucción incorrecta. Ambos operandos están enmemoria, y el procesador no permite este tipo deinstrucciones.

Tabla 5.3: Instrucciones de transferencia de datos

Page 99: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

99 / 198

5.4.2.1. Instrucciones de suma y resta

Las instrucciones ADD y SUB realizan la suma y resta respectivamente de sus dos operandos. En el caso de la resta, la operaciónrealizada es la sustracción del primer operando del segundo. Como tales operaciones precisan de un lugar en el que almacenar elresultado, el segundo operando desempeña las funciones de fuente y destino por lo que se sustituye el valor del segundo operandopor el valor resultante.

El procesador ofrece también las instrucciones INC y DEC que requieren un único operando y que incrementan y decrementanrespectivamente el operando dado. Aunque las instrucciones ADD $1, operando e INC operando realizan la mismaoperación y se podría considerar idénticas, no lo son, pues INC no modifica el bit de acarreo.

La instrucción NEG recibe como único operando un número entero y realiza la operación de cambio de signo.

La Tabla 5.4 muestra ejemplos de utilización de este tipo de instrucciones. Se asume que el símbolo contador se refiere a unoperando almacenado en memoria.

Instrucción Comentario

ADDL $3, contador

Suma la constante 3 al número de 32 bits almacenado apartir de la posición contador. El tamaño vienedeterminado por el sufijo, que en este caso esimprescindible.

SUB %eax, contador Deposita en memoria el número de 32 bits resultante de laoperación contador-%eax.

NEGL contador Cambia de signo el número de 32 bits almacenado enmemoria a partir de la posición contador.

Tabla 5.4: Instrucciones aritméticas

5.4.2.2. Instrucciones de multiplicación

La instrucción de multiplicación tiene dos variantes, IMUL y MUL para números enteros y naturales respectivamente y su formatosupone un caso especial, pues permite la especificación de entre uno y tres operandos.

La versión de IMUL y MUL con un único operando ofrece, a su vez la posibilidad de multiplicar números de 8, 16 y 32 bits.Las instrucciones asumen que el segundo multiplicando está almacenado en el registro%al (para números de 8 bits),%ax (paranúmeros de 16 bits) y%eax (para números de 32 bits). El tamaño del número a multiplicar se deduce del operando explícito dela instrucción.

Si se multiplican dos operandos de n bits, el resultado tiene tamaño doble y debe representarse con 2n bits. Por tanto, si losoperandos son de 8 bits, el resultado de esta instrucción se almacena en%ax, si son de 16 bits se almacena en los 32 bitsresultantes al concatenar los registros%dx:%ax, y si los operandos son de 32 bits, en los 64 bits obtenidos al concatenar losregistros%edx:%eax. En estos dos últimos casos, los registros%dx y%edx contienen los bytes más significativos del resultado.

La versión de IMUL y MUL con dos operandos es más restrictiva que la anterior. El segundo operando puede ser únicamenteuno de los ocho registros de propósito general (no puede ser ni una constante ni un número en memoria) y el tamaño de ambosoperandos puede ser de 16 o 32 bits. Para almacenar el resultado se utiliza el mismo número de bits con los que se representanlos operandos, con lo que se corre el riesgo, si el resultado obtenido es muy elevado, de perder parte del resultado. Esta últimacondición se refleja en los bits de estado del procesador.

La versión de IMUL y MUL con tres operandos es la más restrictiva de todas. Los dos primeros operandos son los multiplicandosy el primero de ellos debe ser una constante. El tercer operando es el lugar en el que se almacena el resultado y sólo puede serun registro de propósito general. Al igual que la versión con dos operandos, los únicos tamaños que se permiten son de 16 y 32bits, y el resultado se almacena en el mismo tamaño que los operandos, por lo que de nuevo se corre el riesgo de pérdida de bitsdel resultado.

La Tabla 5.5 muestra ejemplos de utilización de este tipo de instrucciones. Se asume que el símbolo contador se refiere a unoperando almacenado en memoria.

Page 100: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

100 / 198

Instrucción Comentario

MULB $3Multiplica el número natural 3 representado en 8 bits por elregistro implícito%al y deposita el resultado en%eax. Eltamaño de los operandos lo determina el sufijo B.

IMUL %eaxMultiplica el número entero almacenado en%eax por símismo (operando implícito). El resultado se almacena en elregistro de 64 bits%edx:%eax.

MUL contador, %edi

Multiplica el número natural de 32 bits almacenado a partirde la posición de memoria representada por contadorpor el registro%edi en donde se almacenan los 32 bits demenos peso del resultado.

IMUL $123, contador, %ecx

Multiplica el número de 32 bits almacenado en memoria apartir de la posición contador por la constante $123 yalmacena los 32 bits menos significativos del resultadoen%ecx.

Tabla 5.5: Instrucciones de multiplicación

5.4.2.3. Instrucciones de división entera

Las instrucciones de división de números naturales y enteros devuelven dos resultados, el cociente y el resto, y se almacenanambos valores. De manera análoga a las instrucciones de multiplicación, existen dos versiones IDIV y DIV para división deenteros y naturales respectivamente y el tamaño del dividendo es el doble del divisor. De esta forma, se permite dividir unnúmero de 16 bits entre uno de 8, uno de 32 entre uno de 16 y uno de 64 entre uno de 32.

Su formato admite de forma explícita un único operando que es el divisor, y que puede ser un número de 8, 16 o 32 bits. Eldividendo es implícito y está almacenado en%ax si el divisor es de 8 bits, en el registro de 32 bits resultante de concatenar%-dx:%ax si el divisor es de 16 bits, y en el registro de 64 bits resultante de concatenar%edx:%eax si el divisor es de 32bits.

Los dos resultados que se devuelven también tienen un destino implícito y depende del tamaño de los operandos. Si el divisor esde 8 bits el cociente se almacena en%al y el resto en%ah. Si el divisor es de 16 bits, se utilizan%ax y%dx para cociente y restorespectivamente. En el caso de un divisor de 32 bits, el cociente se devuelve en%eax y el resto en%edx.

La Tabla 5.6 muestra ejemplos de utilización de este tipo de instrucciones. Se asume que el símbolo contador se refiere a unoperando almacenado en memoria.

Instrucción Comentario

IDIVB $-53 Divide el registro%ax por la constante $-53. El cocientese deposita en%al y el resto en%ah.

IDIV %eaxSe divide el número de 64 bits obtenido al concatenar losregistros%edx:%eax entre el propio registro%eax.En%eax se deposita el cociente, y en%edx el resto.

DIVW contador

Divide el número de 32 bits almacenado en el registroobtenido al concatenar%dx:%ax entre el número de 16bits almacenado a partir de la posición de memoriaindicada por contador. En%ax se almacena el cocientey en%dx el resto.

Tabla 5.6: Instrucciones de división

5.4.3. Instrucciones lógicas

En este grupo se incluyen las instrucciones de conjunción, disyunción, disyunción exclusiva y negación. La aplicación prácticade estas instrucciones no es a primera vista del todo aparente, sin embargo, suelen estar presentes en la mayoría de programas.

Page 101: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

101 / 198

Las cuatro instrucciones lógicas consideradas son AND, OR, NOT y XOR para la conjunción, disyunción, negación y disyunciónexclusiva, respectivamente.

Estas instrucciones tienen en común que realizan sus operaciones ‘bit a bit’. Es decir, el procesador realiza tantas operacioneslógicas como bits tienen los operandos tomando los bits que ocupan la misma posición y, por tanto, produciendo otros tantosresultados.

Considérese el caso de la instrucción de conjunción AND con sus dos operandos. Al igual que en el caso de instrucciones comola de suma o resta, el segundo operando es a la vez fuente y destino. El procesador obtiene un resultado de igual tamaño que susoperandos y en el que cada bit es el resultado de la conjunción de los bits de idéntica posición de los operandos. Las instruccionesde disyunción (OR) y disyunción exclusiva (XOR) se comportan de forma análoga.

La instrucción NOT tiene un único operando que es fuente y destino y cambia el valor de cada uno de sus bits.

La Tabla 5.7 muestra ejemplos de utilización de este tipo de instrucciones. Se asume que el símbolo contador se refiere a unoperando almacenado en memoria.

Instrucción Comentario

AND $-1, %eaxCalcula la conjunción bit a bit entre la constante $-1 y elregistro%eax. ¿Qué valor tiene%eax tras ejecutar estainstrucción?

ORL $1, contadorCalcula la disyunción bit a bit entre la constante $1 y elnúmero de 32 bits almacenado en memoria a partir de laposición denotada por contador.

NOTL contadorCambia el valor de los 32 bits almacenados a partir de laposición de memoria que denota contador. El sufijo detamaño es necesario para definir el tamaño del operando.

Tabla 5.7: Instrucciones lógicas

5.4.4. Instrucciones de desplazamiento y rotación

En este grupo se incluyen instrucciones que mediante desplazamientos efectúan operaciones aritméticas de multiplicación y di-visión por potencias de dos. Además, se incluyen también instrucciones que manipulan sus operandos como si los bits estuviesendispuestos de forma circular y permite rotaciones en ambos sentidos.

5.4.4.1. Instrucciones de desplazamiento

Las instrucciones de desplazamiento se subdividen a su vez en dos categorías: desplazamiento aritmético y desplazamientológico.

Las instrucciones de desplazamiento aritmético son aquellas que equivalen a multiplicar y dividir un número por potencias de2. Un desplazamiento de un bit quiere decir que cada uno de ellos pasa a ocupar la siguiente posición (a derecha o izquierda) ypor tanto, dependiendo de cómo se introduzcan nuevos valores y cómo se descarte el bit sobrante, dicha operación es idéntica amultiplicar por 2.

En adelante se asume que el bit más significativo de un número es el de más a su izquierda. La figura 5.5 muestra un desplaza-miento aritmético a izquierda y derecha de un número de 8 bits.

Page 102: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

102 / 198

Figura 5.5: Desplazamiento aritmético de 1 bit en un número de 8 bits

Para que la equivalencia entre los desplazamientos de bits y la operación aritmética de multiplicación y división por 2 seanrealmente equivalentes hay que tener en cuenta una serie de factores.

Si se desplaza un número a la izquierda, el nuevo bit menos significativo debe tener el valor cero.

Si se desplaza a la izquierda un número natural con su bit más significativo a uno se produce desbordamiento.

Si se desplaza un número a la derecha, el nuevo bit más significativo debe tener valor idéntico al antiguo.

Las instrucciones SAL (Shift Arithmetic Left) y SAR (Shift Arithmetic Right) desplazan su segundo operando a izquierda yderecha respectivamente tantas veces como indica el primer operando. En ambas instrucciones, el último bit que se ha descartadose almacena en el bit de acarreo CF. Estas instrucciones tienen la limitación adicional de que el primer operando sólo puede seruna constante o el registro%cl.

La Tabla 5.8 muestra ejemplos de utilización de este tipo de instrucciones. Se asume que el símbolo contador se refiere a unoperando almacenado en memoria.

Instrucción Comentario

SAR $4, %eaxDesplaza 4 bits a la derecha el contenido del registro%eax.Esta operación es equivalente a multiplicar por 16 elregistro%eax.

SALB %cl, contador

Desplaza el byte almacenado en la posición de memoriadenotada por contador tantas posiciones a la izquierdacomo indica el registro%cl. El sufijo de tamaño esnecesario porque a pesar de que el primer operando es unregistro, éste contiene sólo el número de posicionesdesplazar. El tamaño de los datos se deduce, por tanto delsegundo operando.

Tabla 5.8: Instrucciones de desplazamiento aritmético

Las instrucciones de desplazamiento no aritmético son SHR y SHL para desplazar a derecha e izquierda respectivamente. Elcomportamiento y restricciones son idénticas a las instrucciones anteriores con una única diferencia. Los nuevos bits que seinsertan en los operandos tienen siempre el valor cero. Por tanto, dependiendo de los valores de los operandos, las instruccionesSAR y SAL se pueden comportar de forma idéntica.

Page 103: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

103 / 198

5.4.4.2. Instrucciones de rotación

Las instrucciones de rotación permiten manipular un operando como si sus bits formasen un círculo y se rotan en ambos sentidosun número determinado de posiciones.

Las instrucciones ROL y ROR rotan a izquierda y derecha respectivamente el contenido de su segundo operando tantas posicionescomo indica el primer operando. El último bit que ha traspasado los límites del operando se almacena en el bit de acarreo CF.

Las instrucciones RCL y RCR son similares a las anteriores con la excepción que el bit de acarreo CF se considera como partedel operando. El bit que sale del límite del operando se carga en CF y éste a su vez pasa a formar parte del operando.

La figura 5.6 ilustra el funcionamiento de estas instrucciones.

Figura 5.6: Rotación de un operando de 8 bits

Al igual que las instrucciones de desplazamiento aritmético, el primer operando puede ser o una constante o el registro%cl.El tamaño del dato a manipular se deduce del segundo operando, y si este está en memoria, a través del sufijo de tamaño de lainstrucción.

La Tabla 5.9 muestra ejemplos de utilización de este tipo de instrucciones. Se asume que el símbolo contador se refiere a unoperando almacenado en memoria.

Instrucción Comentario

RCR $4, %ebx Rota el registro%ebx cuatro posiciones a su derechautilizando el bit de acarreo CF.

RCLL %cl, contador

Rota a la izquierda tantas posiciones como indica elregistro%cl el operando de 32 bits almacenado enmemoria a partir de la posición denotada por contador.A pesar de que el primer operando es un registro, lainstrucción necesita sufijo de tamaño, pues éste se deduceúnicamente del segundo operando que está en memoria.

ROR %cl, %eaxRota a la derecha el registro%eax tantas posiciones comoindica el registro%cl. El bit CF almacena el bit mássignificativo del resultado.

ROLL %cl, contador

Rota a la izquierda tantas posiciones como indica elregistro%cl el número de 32 bits almacenado en memoriaa partir de la posición contador. De nuevo se precisa elsufijo de tamaño porque éste se deduce únicamente a lavista del segundo operando.

Tabla 5.9: Instrucciones de rotación

5.4.5. Instrucciones de salto

El procesador ejecuta una instrucción tras otra de forma secuencial a no ser que dicho flujo de ejecución se modifique. Lasinstrucciones de salto sirven para que el procesador, en lugar de ejecutar la siguiente instrucción, pase a ejecutar otra en un lugar

Page 104: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

104 / 198

que se denomina ‘destino del salto’.

La instrucción de salto JMP (del inglés jump) tiene un único operando que representa el lugar en el que el procesador debecontinuar ejecutando. Al llegar a esta instrucción, el procesador no realiza operación alguna y simplemente pasa a ejecutarla instrucción en el lugar especificado como destino del salto. El único registro, por tanto, que se modifica es el contador deprograma.

A la instrucción JMP se le denomina también de salto incondicional por contraposición a las instrucciones de salto en las que elprocesador puede saltar o no al destino dependiendo de una condición.

La arquitectura IA-32 dispone de 32 instrucciones de salto condicional. Todas ellas comienzan por la letra J seguida de unaabreviatura de la condición que determina si el salto se lleva a cabo o no. Al ejecutar esta instrucción el procesador consulta estacondición, si es cierta continua ejecutando la instrucción en la dirección destino del salto. Si la condición es falsa, la instrucciónno tienen efecto alguno sobre el procesador y se ejecuta la siguiente instrucción.

Las condiciones en las que se basa la decisión de saltar dependen de los valores de los bits de estado CF, ZF, OF, SF y PF. LaTabla 5.10 muestra para cada instrucción los valores de estos bits para los que se salta a la instrucción destino.

Instrucción Condición Descripción Instrucción Condición Descripción

JA mem

JNBE memCF = 0 y ZF = 0

Salto si mayor,salto si no menoro igual (sinsigno)

JBE mem

JNA memCF = 1 ó ZF = 1

Salto si menor oigual, salto si nomayor (sin signo)

JAE mem

JNB memCF = 0

Salto si mayor oigual, salto si nomenor (sin signo)

JB mem

JNAE memCF = 1

Salto si menor,salto si no mayoro igual (sinsigno)

JE mem

JZ memZF = 1 Salto si igual,

salto si cero.

JNE mem

JNZ memZF = 0 Salto si diferente,

salto si no cero.

JG mem

JNLE memZF = 0 y SF = OF

Salto si mayor, sino menor o igual(con signo)

JLE mem

JNG mem

ZF = 1 ó SF !=OF

Salto si menor oigual, si nomayor (consigno)

JGE mem

JNL memSF = OF

Salto si mayor oigual, si nomenor (consigno)

JL mem

JNGE memSF != OF

Salto si menor, sino mayor o igual(con signo)

JC mem CF = 1 Salto si acarreoes uno

JNC mem CF = 0 Salto si acarreoes cero

JCXZ mem %cx = 0Salto siregistro%cx escero.

JECXZ mem %ecx = 0Salto siregistro%ecx escero.

JO mem OF = 1Salto si el bit dedesbordamientoes uno.

JNO mem OF = 0Salto si el bit dedesbordamientoes cero.

JPO mem

JNP memPF = 0

Salto si paridadimpar, si noparidad.

JPE mem

JP memPF = 1 Salto si paridad

par, si paridad.

JS mem SF = 1 Salto si positivo. JNS mem SF = 0 Salto si negativo.

Tabla 5.10: Instrucciones de salto condicional

Page 105: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

105 / 198

En la tabla se incluyen instrucciones con diferente nombre e idéntica condición. Estos sinónimos son a nivel de lenguaje ensam-blador, es decir, las diferentes instrucciones tienen una codificación idéntica y por tanto corresponden con la misma instrucciónmáquina del procesador.

La utilidad de estas instrucciones se debe entender en el contexto del flujo normal de ejecución de un programa. El resto de ins-trucciones realizan diferentes operaciones sobre los datos, y a la vez modifican los bits de la palabra de estado. Las instruccionesde salto se utilizan después de haber modificado estos bits y para poder tener dos posibles caminos de ejecución.

El ejemplo 5.4 muestra una porción de código ensamblador muestra un posible uso de las instrucciones de salto.

Ejemplo 5.4 Uso de saltos condicionales

MOV $100, %ecxdest2: DEC %ecx

JZ dest1ADD %ecx, %eaxJMP dest2

La instrucción DEC%ecx decrementa el valor del registro%ecx y modifica los bits de la palabra de estado. La instrucción JZprovoca un salto si ZF = 1. Como consecuencia, la instrucción ADD%ecx,%eax se ejecuta un total de 100 veces.

Las instrucciones de salto condicional son útiles siempre y cuando los valores de los bits de estado hayan sido previamenteproducidos por instrucciones anteriores, como por ejemplo, operaciones aritméticas. Pero en algunos casos, la ejecución de unsalto condicional requiere que se realice una operación aritmética y no se almacene su resultado, sino simplemente que se realiceuna comparación. Por ejemplo, si se necesita saltar sólo si un número es igual a cero, en lugar de ejecutar una instrucción ADD,SUB, INC o DEC para que se modifique el bit ZF sólo se necesita comprobar si tal número es cero y modificar los bits de estado.Para este cometido el procesador dispone de las instrucciones de comparación y comprobación.

5.4.6. Instrucciones de comparación y comprobación

Las instrucciones CMP (comparación) y TEST (comprobación) realizan sendas operaciones aritméticas de las que no se guardael resultado obtenido sino que únicamente se modifican los bits de estado.

La instrucción CMP recibe dos operandos. El primero de ellos puede ser de tipo constante, registro u operando en memoria. Elsegundo puede ser únicamente de tipo registro u operando en memoria. La instrucción no permite que ambos operandos esténen memoria. Al ejecutar esta instrucción se resta el primer operando del segundo. El valor resultante no se almacena en lugaralguno, pero sí se modifican los bits de estado del procesador.

Considérese el código mostrado en el ejemplo 5.5. La instrucción de comparación modifica los bits de estado para que la instruc-ción de salto los interprete y decida si debe saltar o continuar ejecutando la instrucción ADD.

Ejemplo 5.5 Instrucción de comparación antes de salto condicional

CMP $0, %eax # Se calcula %eax - 0JE destinoADD %eax, %ebx

La instrucción JE produce un salto cuando el bit de estado ZF tiene el valor 1. Este bit, a su vez se pone a uno si los operandosde la instrucción CMP son iguales. Por tanto, la instrucción JE, cuando va a continuación de una instrucción de comparación, sepuede interpretar como ‘salto si los operandos (de la instrucción anterior) son iguales’.

En la mayoría de las instrucciones de salto condicional detalladas en la sección 5.4.5, las últimas letras del nombre hacenreferencia a la condición que se comprueba cuando se ejecutan a continuación de una instrucción de comparación. Por ejemplo,la instrucción JLE produce un salto cuando los bits de condición cumplen ZF = 1 o SF != OF. Si esta instrucción va precedida deuna instrucción de comparación, ZF es igual a 1 si los dos operandos son iguales. Si SF es diferente a OF la resta ha producidoun bit de signo, y el bit de desbordamiento con valores diferentes. Esta situación se produce si el segundo operando es menorque el primero, de ahí el sufijo LE (del inglés less or equal) en la instrucción de salto. La Tabla 5.11 muestra las combinacionesobtenidas del bit de desbordamiento y la resta para el caso de enteros representados con 2 bits.

Page 106: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

106 / 198

OF, A-BB

(-2) 10 (-1) 11 (0) 00 (1) 01

A

(-2) 10 0, 00 0, 11 0, 10 1, 01(-1) 11 0, 01 0, 00 0, 11 0, 10(0) 00 1, 10 0, 01 0, 00 0, 11(1) 01 1, 11 1, 10 0, 01 0, 00

Tabla 5.11: Resta y bit de desbordamiento de dos enteros de 2 bits

El bit de signo y el de desbordamiento tienen valores diferentes únicamente en el caso en que el primer operando de la resta esmenor que el segundo. Por tanto, la instrucción JLE si se ejecuta a continuación de una instrucción CMP se garantiza que el saltose lleva a cabo si el segundo operando es menor que el primero.

Las instrucciones de salto cuya condición puede interpretarse con respecto a la instrucción de comparación que le precede sonlas que en la descripción mostrada en la tabla Tabla 5.10 incluyen una comparación. Aunque estas instrucciones no debe irnecesariamente precedidas por una instrucción de comparación porque la condición se evalúa con respecto a los bits de estado,generalmente se utilizan acompañadas de éstas.

Para interpretar el comportamiento de una instrucción de comparación seguida de una de salto condicional se puede utilizar lasiguiente regla mnemotécnica:

Salto condicional precedido de comparaciónDada la siguiente secuencia de dos instrucciones en ensamblador:

CMP B, AJcond

donde A y B son cualquier operando y cond es cualquiera de las condiciones posibles, el salto se lleva a cabo si se cumple Acond B.

Por ejemplo, si la instrucción CMP $4,%eax va seguida del salto condicional JL destino, el procesador saltará a destinosi%eax < 4.

La Tabla 5.12 muestra posibles secuencias de instrucciones de comparación y salto condicional.

La posibilidad de saltar a una posición de código dependiendo de una condición está presente en la mayoría de lenguajes deprogramación de alto nivel. Por ejemplo, en el lenguaje Java, la construcción if () {} else {} se implementa a nivel deensamblador basado en instrucción de salto condicional.

La instrucción de comprobación TEST es similar a la de comparación, también consta de dos operandos, el segundo de ellospuede ser únicamente de tipo registro o memoria y no se permite que ambos sean de tipo memoria. La diferencia con CMP es quese realiza una conjunción bit a bit de ambos operandos. El resultado de esta conjunción tampoco se almacena, pero sí modificalos bits de estado OF, CF (ambos se ponen a cero), SF, ZF y PF.

La Tabla 5.13 muestra posibles secuencias de instrucciones de comprobación y salto condicional.

5.4.7. Instrucciones de llamada y retorno de subrutina

Una de las construcciones más comunes en la ejecución de programas es la invocación de porciones de código denominadassubrutinas con un conjunto de parámetros. Este mecanismo es en el que está basada la invocación de procedimientos, métodos ofunciones en los lenguajes de programación de alto nivel.

Para implementar este mecanismo, el procesador dispone de dos instrucciones. La instrucción CALL tiene un único parámetroque es la posición de memoria de la primera instrucción de una subrutina. El efecto de esta instrucción es similar a la de saltoincondicional con la diferencia de que el procesador guarda ciertos datos en lugares para facilitar el retorno una vez terminada lala ejecución de la subrutina.

Page 107: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

107 / 198

Código Comentario

inicio: inc %eaxcmp $128, %eaxjae final...jmp inicio

final: mov $’A, %cl

...

El salto a final se produce si el registro%eax contieneun valor mayor o igual a 128. La condición del salto espara operandos sin signo, es decir, el resultado de lacomparación se interpreta como si los operandos fuesennúmeros naturales.

cmp $12, %eaxjle menormov $10, %eax....jmp final

menor: mov $100, %eax...

final: inc %ebx

El salto a menor se produce si el registro%eax es menor oigual que 12. La condición del salto es para operandos consigno (números enteros).

Tabla 5.12: Secuencias de instrucciones de comparación y salto condicional

Código Comentario

testl $0x0080, contadorjz ignora....

ignora: incl %ebx

El salto a ignora se produce si el operando de 32 bitsalmacenado en memoria a partir de la posición contadortiene su octavo bit igual a cero. Esta instrucción precisa elsufijo de tamaño.

test 0xFF00FF00, %eaxjnz pl....jmp final

pl: mov %eax

...

El salto a pl se produce si alguno de los bits en lasposiciones 8 a 15 o 24 a 31 del registro%eax es igual auno.

Tabla 5.13: Secuencias de instrucciones de comprobación y salto condicional

Page 108: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

108 / 198

La instrucción RET es la que se utiliza al final de una subrutina para retomar la ejecución en el punto anterior a la invocación me-diante la instrucción CALL. No recibe ningún parámetro y el procesador gestiona internamente el lugar en el que debe continuarla ejecución.

En el capítulo 8 se estudia con todo detalle la utilización de estas instrucciones para implementar construcciones presentes enlenguajes de programación de alto nivel.

5.5. Ejercicios

1. Utilizando cualquier buscador de internet, localiza los tres volúmenes del documento IA-32 Intel Architecture SoftwareDeveloper’s Manual. Utilizando el volumen 2, responde a las siguientes preguntas:

a. Una duda común sobre la instrucción de pila POP es la siguiente. El incremento del registro apuntador de pila%esp,¿se hace antes o después de escribir el dato de la cima de la pila en el lugar indicado en la instrucción?

b. ¿Qué código de operación en hexadecimal tiene la instrucción PUSH $4?

c. ¿Qué hace la instrucción LAHF? ¿Cuántos operandos recibe?

d. ¿Qué hace la operación NOP? ¿Qué diferencia hay entre la instrucción NOP y la instrucción XCHG%eax,%eax?

e. ¿Qué hace la instrucción STC?

f. ¿Qué flags de la palabra de estado modifica la ejecución de una instrucción de resta?

2. Pensar una situación en un programa en la que la única posibilidad de multiplicar dos números sea mediante la instruccióncon un único operando.

3. Enunciar las condiciones que deben cumplir los operandos para que las instrucciones SAL y SHL se comporten de formaidéntica. Enunciar estas condiciones para las instrucciones SAR y SHR.

Page 109: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

109 / 198

Capítulo 6

El programa ensamblador

Los programas escritos en lenguaje ensamblador, a pesar de representar instrucciones del lenguaje máquina del procesador, noson directamente ejecutables por éste sino que es necesario traducirlas a su codificación en binario. Este proceso de traducción esfácilmente automatizable, y por tanto se dispone de programas denominados ensambladores (o más genéricamente compiladoresque se encargan de esta tarea.

El ensamblador es un programa que recibe como datos de entrada uno o varios ficheros de texto plano con un conjunto deinstrucciones y datos escritos en lenguaje ensamblador y produce un fichero binario y ejecutable que contiene la codificaciónbinaria del programa. La figura 6.1 muestra el funcionamiento del programa ensamblador.

Figura 6.1: El programa ensamblador

En general, a los programas encargados de traducir de un lenguaje de programación a otro se les denomina ‘compiladores’ y todosellos trabajan de forma similar. Dado un conjunto de ficheros escritos en un lenguaje, producen como resultado otro fichero quecontiene la traducción a un segundo lenguaje. En el caso del ensamblador, la traducción es de lenguaje ensamblador a lenguajemáquina.

En adelante se utilizarán los términos ‘compilador’ y ‘ensamblador’ de forma indistinta y siempre en referencia al programa quetraduce de lenguaje ensamblador a lenguaje máquina.

Así como el lenguaje máquina de un procesador es único e inmutable (a no ser que se rediseñe el procesador), pueden coexistirmúltiples lenguajes ensamblador que representen el mismo lenguaje máquina. La representación de las instrucciones mediantecadenas alfanuméricas es un convenio utilizado para facilitar su escritura, por lo que pueden existir múltiples convenios de estetipo siempre y cuando se disponga del ensamblador los que traduzca al lenguaje máquina del procesador.

En el caso concreto del sistema operativo Linux, se incluye como parte de las herramientas del sistema un compilador capazde traducir de lenguaje ensamblador a lenguaje máquina. Su nombre es as. En la práctica este programa lo suelen invocar otroscompiladores tales como gcc que es un compilador del lenguaje de alto nivel C a lenguaje máquina, pero también permite latraducción de ficheros con código ensamblador invocando internamente el programa as.

Page 110: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

110 / 198

6.1. Creación de un programa ejecutable en ensamblador

La figura 6.2 muestra un programa en lenguaje ensamblador creado mediante un editor de texto plano, un programa que guardaúnicamente el texto codificado en formato ASCII o UNICODE sin información alguna sobre estilo. El primer paso, por tanto,para la obtención de un programa ejecutable es la creación de un fichero de texto que contenga el código.

Figura 6.2: Estructura de un programa en ensamblador

Un programa consta de varias secciones separadas cada una de ellas por palabras clave que comienzan por el símbolo ‘.’. Lapalabra .data que aparece en la primera línea no tiene traducción alguna para la ejecución, sino que es la forma de notificar alensamblador que a continuación se encuentran definidos conjunto de datos. A este tipo de palabras que comienzan por punto seles denomina ‘directivas’.

El programa tiene definido un único dato que se representa como una secuencia de caracteres. La línea que contiene .asciz(también una directiva) seguida del string entre comillas es la que instruye al ensamblador para crear una zona de memoria condatos, y almacenar en ella el string que se muestra terminado por un byte con valor cero. El efecto de la directiva .asciz esque, al comienzo de la ejecución de programa, este string esté almacenado en memoria.

Antes de la directiva .asciz se incluye la palabra dato seguida por dos puntos. Esta es la forma de definir una etiqueta onombre que luego se utilizará en el código para acceder a estos datos.

La línea siguiente contiene la directiva .text que denota el comienzo de la sección de código. La directiva .global maincomunica al ensamblador que la etiqueta main es globalmente accesible desde cualquier otro programa.

A continuación se encuentran las instrucciones en ensamblador propiamente dichas. Al comienzo del código se define la etiquetamain que identifica el punto de arranque del programa.

Una vez creado y guardado el fichero de texto con el editor, se debe invocar el compilador. En una ventana en el que se ejecute unintérprete de comandos y situados en el mismo directorio en el que se encuentra el fichero ejemplo.s se ejecuta el siguientecomando:

gcc -o ejemplo ejemplo.s

Page 111: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

111 / 198

El compilador realiza una tarea similar a la de un compilador de un lenguaje de alto nivel como Java. Si hay algún error en elprograma se muestra la línea y el motivo. Si el proceso de traducción es correcto, se crea un fichero ejecutable. En el comandoanterior, se ha instruido al ensamblador, por medio de la opción -o ejemplo para que el programa resultante se deposite en elfichero con nombre ejemplo.

El compilador también es capaz de procesar más de un fichero de forma simultanea. Esto es útil cuando el código de un programaes muy extenso y está fraccionado en varios ficheros que deben combinarse para obtener un único ejecutable. En tal caso elcomando para compilar debe incluir el nombre de todos los ficheros necesarios.

Si el compilador no detecta ningún error en la traducción, el fichero ejemplo está listo para ser ejecutado por el procesador. Paraello simplemente se escribe su nombre en el intérprete de comandos (en la siguiente línea, el símbolo $ representa el mensajeque imprime siempre el intérprete de comandos):

$ ejemploMi Primer Programa Ensamblador$

Todo programa ensamblador debe seguir el siguiente patrón:

.data # Comienzo del segmento de datos

<datos del programa>

.text # Comienzo del código

.global main # Obligatorio

main:<Instrucciones>

ret # Obligatorio

Se pueden incluir comentarios en el código a partir de símbolo ‘#’ hasta el final de línea y son ignorados por el compilador.Basado en este patrón, el programa de la figura 6.2 ha ejecutado las instrucciones:

push %eaxpush %ecxpush %edx

push $datocall printfadd $4, %esp

pop %edxpop %ecxpop %eax

ret

Las primeras tres instrucciones depositan los valores de los registros%eax,%ecx y%edx en la pila. Las tres instruccionessiguientes se encargan de poner la dirección del string también en la pila (instrucción push), invocar la rutina externa printfque imprime el string (instrucción call) y sumar una constante al registro%esp para restaurar el valor inicial del puntero a lacima de la pila. Las tres últimas instrucciones restauran el valor original en los registros previamente guardados en la pila.

A continuación se estudia en detalle la sintaxis de las diferentes construcciones permitidas en el lenguaje ensamblador.

6.2. Definición de datos

Como todo lenguaje de programación, se permiten definir tipos de datos así como su contenido. En el caso del ensamblador,estos tipos no permiten estructuras complejas ni heterogéneas. Todas las definiciones deben incluirse en una sección del código

Page 112: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

112 / 198

que comience por la directiva .data. Los datos se almacenan en posiciones contiguas de memoria, es decir, dos definicionesseguidas hacen que los datos se almacenen uno a continuación de otro.

La principal dificultad para manipular los datos en ensamblador es que cuando el procesador accede a ellos, no se realiza ningúntipo de comprobación. Aunque se definan datos con cierto tamaño y estructura en memoria, el procesador trata estos datos comouna simple secuencia de bytes. Esta es una diferencia sustancial con los lenguajes de programación de alto nivel tales comoJava. La definición de datos en ensamblador se realiza a través de directivas (descritas a continuación) que únicamente reservanespacio en memoria con los datos pertinentes, pero no se almacena ningún tipo de información sobre su tamaño.

Los lenguajes de alto nivel contienen lo que se conoce como un ‘sistema de tipos’ que consiste en un conjunto de reglas quepermiten la definición de tipos de datos así como el mecanismo para comprobar su corrección. En ensamblador, al tratarse delos datos que manipula directamente el procesador, no se dispone de tal sistema, y por tanto se manejan como si fuese simplessecuencias de bytes.

6.2.1. Definición de bytes

La definición de valores numéricos almacenados en bytes se realiza mediante la directiva .byte seguida de uno o varios valoresseparados por comas. Cuando el programa comienza la ejecución, se han inicializado tantas posiciones en memoria como indicala directiva con los valores dados. El ejemplo 6.1 muestra ejemplos de utilización de la directiva .byte así como los valoresalmacenados en memoria.

Ejemplo 6.1 Definición de bytes en ensamblador y sus valores en memoria

datos: .byte 38, 0b11011101, 0xFF, ’A, ’ ←↩b

Si el valor numérico especificado es menor que cero o mayor que 255 el compilador notifica la anomalía con un error.

6.2.2. Definición de enteros

La definición de enteros de 32 bits se hace mediante la directiva .int seguida de un número o una lista de números enterosseparados por comas. Los números se codifican con 4 bytes almacenados en little endian. El ejemplo 6.2 muestra ejemplos dedefiniciones de enteros.

Ejemplo 6.2 Definiciones de números enteros y sus valores en memoria

nums: .int 3, 4, 5.int 0x12AB, 0x10ab, 0b111000, 0 ←↩

B111000.int 21

.int 07772

La directiva .long es un sinónimo de .int y también define enteros de 32 bits. Las directivas .word y .quad son análogasa las anteriores pero definen enteros de 16 y 64 bits respectivamente.

Page 113: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

113 / 198

6.2.3. Definición de strings

La definición de strings se puede hacer con dos formatos diferentes mediante la utilización de tres directivas. La directiva .as-cii permite la definición de uno o más strings entre comillas y separadas por comas. Cada símbolo de cada strings codifica conun byte en ASCII utilizando posiciones consecutivas de memoria. Se utilizan tantos bytes como la suma de los símbolos de cadastring.

La directiva .asciz es similar a la anterior, se escribe seguida de uno o más strings separados por comas, pero cada uno deellos se codifica añadiendo un byte con valor cero a final del string. Este formato se suele utilizar para detectar el final del string.La directiva .string es un sinónimo de la directiva .asciz.

El ejemplo 6.3 muestra la utilización de las directivas de definición de strings y los valores que se almacenan en memoria. Losbytes resaltados corresponden son los que añaden las directivas .asciz y .string al final de cada string.

Ejemplo 6.3 Definición de strings y sus valores en memoria

msg: .ascii "S 1", "S 2".asciz "S 3", "S 4"

.string "S final"

6.2.4. Definición de espacio en blanco

La directiva .space seguida de dos números separados por una coma permite la reserva de espacio en memoria. El primer valordenota el número de bytes que se reservan y el segundo es el valor que se utiliza para inicializar dichos bytes y debe estar entre0 y 255. En el caso de que este parámetro se omita, la memoria se reserva inicializada al valor cero.

El uso principal de esta directiva es para reservar espacio que, o se debe inicializar al mismo valor, o su valor será calculado ymodificado por el propio programa. El ejemplo 6.4 muestra el uso de la directiva así como su efecto en memoria.

Ejemplo 6.4 Definiciones de espacio en blanco y su valor en memoria

result: .space 4, 0.space 4

.space 8, 0xFF

6.3. Uso de etiquetas

En lenguaje ensamblador se permite la definición de un conjunto de datos y las instrucciones para manipularlos que se traducen asu codificación binaria y se produce un fichero ejecutable. Antes de comenzar la ejecución del programa, los datos e instruccionesen binario se cargan en la memoria RAM del sistema. Pero ¿en qué posición de memoria está almacenado el programa?

El valor de esta dirección de memoria, o de la dirección en la que está almacenado cualquier dato o instrucción, no se sabe hastael momento en el que se ejecuta el programa porque es el sistema operativo el que lo decide, y tal decisión se aplaza hasta el

Page 114: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

114 / 198

último instante para así poder ubicar cada programa en el lugar más conveniente en memoria. El sistema operativo está ejecutandomúltiples programas de forma simultánea, y por tanto, necesita esta flexibilidad para poder hacer un mejor uso de la memoria.

Pero, si no se sabe el valor de la dirección de memoria de ningún dato ni instrucción, ¿cómo se puede, por ejemplo, acceder a undato en memoria? Para ello se precisa su dirección, pero el valor numérico de esta no se sabe cuando se escribe un programa.

El lenguaje ensamblador soluciona este problema mediante el uso de ‘etiquetas’. Las etiquetas no son más que nombres que seponen al comienzo de una línea (ya sea definición de datos o una instrucción) seguido por dos puntos. Dicho nombre representala posición de memoria en la que está almacenado el dato o instrucción definido justo a continuación.

Estas etiquetas son, por tanto, un punto de referencia en memoria que el ensamblador sabe interpretar de forma correcta y que enel momento de ejecución serán reemplazados por el valor numérico de la dirección de memoria pertinente.

La definición de una etiqueta no sólo permite referirse a los datos almacenados en esa posición, sino que ofrece un mecanismopor el que acceder a los datos en posiciones cercanas a ella mediante simples operaciones aritméticas sobre la dirección querepresenta. Considérese de nuevo la representación en memoria de los enteros definidos en el ejemplo 6.2. La figura 6.3 ilustracomo se pueden deducir las direcciones de los demás enteros en base al símbolo nums:.

Figura 6.3: Etiqueta y direcciones relativas a ella

Dado que la directiva .int define valores enteros representados por 32 bits, de la definición de la etiqueta nums se puedendeducir los valores de las direcciones en las que se almacenan el resto de números enteros definidos. Para efectuar estos cálculoses imprescindible saber el tamaño de la información almacenada a partir de la etiqueta.

Las etiquetas, por tanto, se pueden definir en cualquier lugar del código y son únicamente símbolos que representan una direcciónde memoria cuyo valor no se sabe y se utilizan como puntos de referencia para acceder a los datos en memoria de su alrededor.Pero su uso en ensamblador tiene dos versiones igualmente útiles. La primera es acceder al valor contenido en la posición dememoria a la que se refieren. Para ello se incluye en las instrucciones ensamblador el nombre de la etiqueta tal cual se ha definido(sin los dos puntos).

Pero a menudo es necesario manipular la propia dirección de memoria que representa dicha etiqueta. Aunque dicho valor esdesconocido, nada impide que se escriban instrucciones máquina que operen con él. El ensamblador permite referirse al valor dela dirección de memoria que representa una etiqueta precediendo su nombre del símbolo $.

Si una instrucción ensamblador contiene como operando el nombre de una etiqueta, este operando es de tipo dirección de memoria(ver la sección 5.3.3). En cambio, si el operando es el nombre de una etiqueta precedido por $, este operando es de tipo constante.

Esta nomenclatura para diferenciar entre el valor al que apunta una etiqueta y su valor como dirección en memoria es consistentecon la nomenclatura de operandos. Dada una etiqueta, de los dos valores, al que apunta en memoria y su dirección, es este últimoel que permanece constante a lo largo de la ejecución, y por tanto se representa con el prefijo $. En cambio, el valor en memoriaal que apunta es variable y por ello se representa únicamente por el nombre de la etiqueta.

El ejemplo 6.5 muestra una porción de código en la que se define una etiqueta y se manipula mediante instrucciones máquina.

Page 115: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

115 / 198

Ejemplo 6.5 Definición y manipulación de etiquetas

.datadato: .int 3, 4

.string "Mensaje"

.byte 17

...mov dato, %eaxadd $5, %eaxmov %eax, datomovl $4, dato...mov $dato, %ebxadd $8, %ebx...

La etiqueta dato corresponde con la dirección de memoria en la que está almacenado el entero de 32 bits con valor 3. En elprimer grupo de instrucciones, la instrucción mov dato,%eax mueve el número 3 al registro%eax. Nótese que el operandocarece del prefijo $ y por tanto se refiere al valor almacenado en memoria. A continuación se suma la constante 5 y se transfiereel valor en%eax de nuevo a la posición de memoria referida por dato.

La instrucción movl $4, dato requiere especial atención. El sufijo de tamaño es necesario para desambiguarla porque ni laconstante $4 ni el segundo operando contienen información sobre su tamaño.La información de una etiqueta es únicamente ladirección a la que representa sin ningún tipo de información sobre el tamaño de los datos. Por tanto, a pesar de que dato ha sidodefinida en una línea en la que se reserva espacio para enteros, cuando se utiliza en una instrucción y el otro operando tampocoofrece información sobre el tamaño, requiere el sufijo.

En el segundo grupo de instrucciones, la instrucción mov $dato,%ebx carga en el registro%ebx el valor de la dirección dememoria que representa la etiqueta. Este valor es imposible de saber en tiempo de programación, pero se puede manipular aligual que cualquier otro número. Tras ejecutar la última instrucción, el registro%ebx contiene la dirección de memoria en la queestá almacenada la primera letra del string. Esto se deduce de las definiciones de datos y sus tamaños. Los dos números ocupan8 bytes, con lo que en la posición $dato + 8 se encuentra la letra ‘M’ del string Mensaje.

Las etiquetas no sólo se utilizan en las definiciones de datos sino también en instrucciones del código. Los destinos de los saltosreciben como operando una dirección de memoria, que por tanto debe ser una etiqueta.

Se pueden definir tantas etiquetas como sea preciso en un programa sin que por ello se incremente el tamaño del programa. Lasetiquetas son símbolos que utiliza el programa ensamblador para utilizar en lugar de los valores numéricos de las direcciones quese sabrán cuando el programa comience su ejecución.

El compilador gcc utilizado para traducir de lenguaje ensamblador a lenguaje máquina asume que el punto de comienzo deprograma está marcado por la presencia de la etiqueta con nombre main. Por tanto, al escribir un programa que sea traducidopor gcc se debe definir la etiqueta main en el lugar del código que contenga su primera instrucción máquina.

6.4. Gestión de la pila

El desarrollo de programas en ensamblador tiene una serie de particularidades derivadas de la proximidad al procesador con laque se trabaja. Uno de los cometidos de los lenguajes de programación de alto nivel tales como Java es precisamente el ofreceral programador un entorno en el que se oculten los aspectos más complejos de la programación en ensamblador.

La pila se utiliza como depósito temporal de datos del programa en ejecución. Las operaciones push y pop permiten depositary obtener datos de la pila, pero no son las únicas que modifican su contenido. El propio procesador también utiliza la pila paraalmacenar datos temporales durante la ejecución. Esto implica que los programas en ensamblador tienen ciertas restricciones almanipular la pila.

La más importante de ellas es que la cima de la pila debe ser exactamente la misma antes del comienzo de la primera instrucciónde un programa y antes de la instrucción RET que termina su ejecución. Cuando se arranca un programa, el sistema operativoreserva espacio para la pila y almacena el valor pertinente en el registro%esp. Por motivos que se explican en detalle en elcapítulo 8, el valor de este registro debe ser el mismo al terminar la ejecución de un programa.

Page 116: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

116 / 198

Nótese que el respetar esta regla no implica que la pila no pueda utilizarse. Al contrario, como la cima debe ser idéntica alcomienzo y final del programa, las instrucciones intermedias sí pueden manipular su contenido siempre y cuando al final delprograma se restaure el valor de la cima que tenía al comienzo.

En un programa, esta limitación se traduce en que cada dato que se deposite en la pila debe ser descargado antes de que finaliceel programa. En el medio del código, la pila puede almacenar los datos que el programador considere oportunos.

Además de inicializar el registro%esp, el sistema operativo también deposita valores en los registros de propósito general. Laejecución del programa escrito en ensamblador la inicia el sistema mediante una llamada a la subrutina con nombre main (deahí que éste sea el punto de comienzo del programa) y por tanto, los registros tienen todos ciertos valores iniciales.

La regla a respetar en los programas ensamblador es que al término de la ejecución de un programa, el valor de los registros depropósito general debe ser exactamente el mismo que tenían cuando se comenzó la ejecución (en la práctica no todos los registrosdeben ser restaurados, pero por simplicidad se ha adoptado la regla para todos ellos).

De nuevo, el que el valor de los registros tenga que ser idéntico al comienzo y al final de un programa no quiere decir que no sepuedan utilizar. Simplemente se deben guardar los valores iniciales de aquellos registros que se utilicen y restaurarlos antes determinar la ejecución.

El lugar más apropiado para guardar los valores iniciales de estos registros es precisamente la pila. No es preciso reservarespacio de antemano, pues la pila ya lo tiene reservado, y mediante varias instrucciones PUSH se depositan los registros que semodifiquen en el código antes de ejecutar las instrucciones propias del cálculo. Luego, justo antes del final de la ejecución serestauran mediante las instrucciones POP. El ejemplo 6.6 muestra una porción de un programa que modifica los registros%ea-x,%ebx,%ecx y%edx,

Ejemplo 6.6 Instrucciones para salvar y restaurar registros

main: push %eaxpush %ebxpush %ecxpush %edx

# Instrucciones del programa que modifican los 4 registros

pop %edxpop %ecxpop %ebxpop %eax

ret

Las instrucciones para guardar la copia de los registros que se modifican se realiza justo al principio del código. De formaanáloga, las instrucciones para restaurar estos valores se realizan justo antes de la instrucción RET. Asimismo, el orden en el quese salvan y restauran los registros es el inverso debido a cómo se almacenan en la pila. El orden en el que se depositan los datosen la pila es irrelevante, tan sólo se deben restaurar en orden inverso al que se han depositado.

Todo programa ensamblador, por tanto, debe comenzar y terminar con instrucciones de PUSH y POP de los registros que semodifiquen en su interior.

La utilización de la pila para almacenar los valores de los registros modificados respeta el convenio de mantener la cima de lapila idéntica al comienzo y final del programa. Como el número de operaciones PUSH es idéntico al número de operaciones POP,mientras que en el código interno del programa todo dato que se deposite en la pila se extraiga, la cima de la pila es idéntica alcomienzo y final.

A la hora de desarrollar programas en ensamblador, se recomienda primero escribir el código interno de un programa y cuandodicho código se suponga correcto completarlo con las instrucciones que salvan y restauran los registros que se modifican. Engeneral, los datos que se almacenan en la pila se hace de forma temporal y deben eliminarse una vez terminada la tarea para laque se han almacenado.

Page 117: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

117 / 198

6.5. Desarrollo de programas en ensamblador

El desarrollo de programas en ensamblador requiere un conocimiento en detalle de la arquitectura del procesador y una meticu-losidad extrema a la hora de decidir qué instrucciones y datos utilizar. Al trabajar con el lenguaje máquina del procesador, lacomprobación de errores de ejecución es prácticamente inexistente. Si se ejecuta una instrucción con operandos incorrectos, elprocesador los interpretará tal y como estipula su lenguaje máquina, con lo que es posible que la ejecución del programa produzcaresultados inesperados.

Desafortunadamente no existe un conjunto de reglas que garanticen un desarrollo simple de los programas. Esta destreza seadquiere mediante la práctica y, más importante, mediante el análisis detenido de los errores, pues ponen de manifiesto aspectosde la programación que se han ignorado.

Las recomendaciones que se hacen para el desarrollo de programas en lenguaje de alto nivel adquieren todavía más relevanciaen el contexto del lenguaje ensamblador. Sin ser de ninguna manera una lista exhaustiva, se incluyen a continuación las másrelevantes.

El valor de los registros y el puntero de pila antes de ejecutar la última instrucción del programa deben ser idénticos a losvalores que tenían al comienzo.

Se deben evitar las operaciones innecesarias. Por ejemplo, salvar y restaurar todos los registros independientemente de si sonutilizados o no.

Debido al gran número de instrucciones disponibles y a su simplicidad siempre existen múltiples forma de realizar una ope-ración. Generalmente elige aquella que proporciona una mayor eficiencia en términos de tiempo de ejecución, utilización dememoria o registros, etc.

Mantener un estilo de escritura de código que facilite su legibilidad. Escribir las etiquetas a principio de línea, las instruccionestodas a la misma altura (generalmente mediante ocho espacios), separar los operandos por una coma seguida de un espacio,etc.

La documentación en el código es imprescindible en cualquier lenguaje de programación, pero en el caso del ensamblador,es crucial. Hacer uso extensivo de los comentarios en el código facilita la comprensión del mismo además de simplificarla detección de errores. Los comentarios deben ser lo más detallados posible evitando comentar instrucciones triviales. Espreferible incluir comentarios de alto nivel sobre la estructura global del programa y los datos manipulados.

La mayor parte de errores se detectan cuando el programa se ejecuta. No existe una técnica concreta para detectar y corregirun error, pero se debe analizar el código escrito de manera minuciosa. En ensamblador un simple error en el nombre de unregistro puede producir que un programa sea incorrecto.

6.6. Ejemplo de programa en ensamblador

El ejemplo 6.7 muestra un programa de ejemplo escrito en ensamblador que dados cuatro enteros almacenados en memoria,suma sus valores y deposita el resultado en el lugar que denota la etiqueta result.

Page 118: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

118 / 198

Ejemplo 6.7 Programa que suma cuatro enteros

.data # Comienza la sección de datosnum1: .int 10num2: .int 23num3: .int 34num4: .int 43result: .space 4 # Deposita aquí el resultado

.text # Comienza la sección de código

.global main # main es un símbolo global

main:push %eax # Salva registros

mov num1, %eax # Carga primer número y acumulaadd num2, %eaxadd num3, %eaxadd num4, %eax

mov %eax, result # Almacena resultado

pop %eax # Restaura registrosret

La sección de definición de datos contiene los cuatro enteros con sus respectivas etiquetas y los cuatro bytes de espacio vacío enel que se almacenará su suma. La directiva .space tiene un único parámetro, con lo que se reserva espacio en memoria pero nose inicializa.

El programa utiliza el registro%eax para acumular los valores de los números, por lo que necesita ser salvado en la pila alcomienzo y restaurado al final.

Tras salvar%eax en la pila la siguiente instrucción simplemente mueve el primer número al registro%eax. No es posible sumardos números que están almacenados en memoria, por lo que el programa carga el primer valor en un registro y luego suma losrestantes números a este registro.

Finalmente, el programa almacena el resultado de la suma en la posición de memoria con etiqueta result, restaura los registrosutilizados (en este caso sólo%eax) y termina la ejecución con la instrucción RET.

6.7. Ejercicios

1. Escribir el equivalente de las siguientes definiciones de datos en ensamblador pero utilizando únicamente la directiva.byte.

.int 12, 0x34, ’A

.space 4, 0b10101010

.ascii "MSG."

.asciz "MSG. "

2. Dada la siguiente definición de datos:

dato: .int 0x10203040, 0b10.string "Mensaje en ASCII".ascii "Segundo mensaje"

Page 119: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

119 / 198

Si la etiqueta dato ser refiere a la posición de memoria 0x00001000, calcular la dirección de memoria de los siguientesdatos:

El byte con valor 0x30 del primer entero definido.

El byte de más peso del segundo número entero definido.

La letra ‘A’ del primer string definido.

El espacio en blanco entre las dos palabras de la última definición.

Page 120: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

120 / 198

Capítulo 7

Modos de Direccionamiento

En este capítulo se estudia una parte concreta de la ejecución de cada instrucción máquina: la obtención de los operandos. Trasrecibir una instrucción el procesador debe obtener los operandos necesarios que están almacenados en registros de propósitogeneral, en la propia instrucción o en memoria. El acceso a los dos primeros es sencillo, pero el acceso a memoria puede serarbitrariamente complejo.

A pesar de que cada dato almacenado en memoria tiene una dirección, en la práctica, se suelen utilizar un conjunto de operacionesaritméticas para obtenerla. La figura 7.1 muestra un ejemplo de las operaciones necesarias para obtener la dirección de unelemento en una tabla de enteros.

Figura 7.1: Dirección de un elemento en una tabla de enteros

Supóngase una tabla de números enteros de 32 bits almacenados a partir de la posición 100 de memoria. El único dato del que sedispone es dicho valor. ¿Cómo se puede acceder al elemento con índice 3 de la tabla? Sabiendo que los enteros tienen 4 bytes detamaño, sumando a la dirección base de la tabla el tamaño de los 3 números anteriores se obtiene la dirección del entero deseado.

Los cálculos para obtener una dirección de memoria suelen requerir operaciones de suma, resta, multiplicación y división y portanto pueden realizarse utilizando las instrucciones aritméticas del procesador. Para acceder a un operando en memoria se calculaprimero su dirección con las operaciones pertinentes y luego se accede a memoria.

Pero estos dos pasos resultan ser extremadamente frecuentes en la ejecución de los programas convencionales. Una parte impor-tante de las instrucciones ejecutadas por un procesador están destinadas al cálculo de la dirección de un operando que se necesitapara una operación posterior.

A la vista de esta situación, el diseño de los procesadores ha ido incorporando a la propia instrucción máquina la posibilidad derealizar ciertos cálculos sencillos para la obtención de la dirección de sus operandos. La estrategia consiste en incluir los cálculosmás comunes como parte de la instrucción y de esta forma conseguir secuencias de instrucciones más compactas, puesto que las

Page 121: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

121 / 198

operaciones aritméticas se hacen igual pero sin necesidad de ejecutar múltiples instrucciones, y por consiguiente se obtiene unamayor eficiencia en la ejecución.

Para ilustrar la ventaja de los modos de direccionamiento considérese la situación en la que el procesador debe acceder a unoperando en memoria cuya dirección d se obtiene mediante la ecuación 7.1. Supóngase que se debe sumar el valor 300 al númerode 32 bits almacenado en esta posición. Una posible secuencia de instrucciones para realizar tal operación se ilustra en el ejemplo7.1

d = 1000+ %eax+(%ebx∗4)

EQUATION 7.1: Expresión de la dirección de un dato en memoria

Ejemplo 7.1 Cálculo de la dirección de un operando mediante instrucciones

mov %ebx, %ecx # %ecx = %ebxsal $2, %ecx # %ecx = (%ebx * 4)add %eax, %ecx # %ecx = %eax + (%ebx * 4)add $1000, %ecx # %ecx = 1000 + %eax + (%ebx * 4)addl $300, (%ecx) # Sumar 300 a la posición indicada por %ecx

Las cuatro primeras instrucciones calculan el valor de la dirección del operando y es únicamente la última la que realiza el accesoy la suma de la constante $300. Esta última instrucción está accediendo a memoria de una forma especial. La expresión de susegundo operando (%ecx) indica que el operando está en memoria en la posición contenida en el registro%ecx. Se precisael sufijo de tamaño porque el primer operando es una constante, y el segundo operando, a pesar de contener el nombre de unregistro, en realidad especifica una dirección de memoria.

Supóngase ahora que el lenguaje máquina del procesador permite escribir la siguiente instrucción:

addl $300, 1000(%eax, %ebx, 4)

El efecto de esta instrucción es exactamente el mismo que el de las cinco instrucciones del ejemplo 7.1. Se realiza la suma de300 y el número de 32 bits almacenado en memoria en la posición obtenida al sumar 1000, el contenido del registro%eax y elcontenido del registro%ebx previamente multiplicado por cuatro. Este segundo operando es a la vez fuente y destino.

La existencia de tal instrucción en el lenguaje máquina tiene la ventaja de que en una instrucción el procesador recibe mucha másinformación sobre la operación a realizar. En el primer caso se precisan cinco instrucciones, o lo que es lo mismo, cinco ciclosde ejecución como los descritos en la sección 4.2. En el segundo caso, con una única instrucción el procesador dispone de todoslos ingredientes para realizar los cálculos. La mejora en rendimiento no se deriva del número de operaciones aritméticas, puesson exactamente las mismas en ambos casos, sino del número de instrucciones que se ejecutan.

Pero a cambio, el principal inconveniente de esta solución es que la codificación y longitud de las instrucciones se complica tantocomo complejas sean las operaciones que se permiten en una instrucción. En este caso se realizan dos sumas y una multiplicaciónpara obtener la dirección de un operando que a su vez participa en la suma final.

Al conjunto de métodos que el lenguaje máquina de un procesador ofrece para acceder a sus operandos se les denomina modos dedireccionamiento. El número de métodos diferentes depende de cada procesador y varía enormemente entre diferentes diseños.Los modos de direccionamiento de la arquitectura IA-32 contemplan el acceso a operandos como los utilizados en la instrucciónaddl $300, 1000(%eax,%ebx, 4).

La figura 7.2 ilustra el funcionamiento de los modos de direccionamiento de un procesador.

Page 122: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

122 / 198

Figura 7.2: Funcionalidad de los modos de direccionamiento

En general un modo de direccionamiento es un procedimiento que dado un conjunto de bits o campos de la instrucción calculael lugar en el que se encuentra almacenado un operando.

7.1. Notación

Para especificar en detalle el funcionamiento de los modos de direccionamiento se precisa una notación para referirse a loscomponentes de las operaciones necesarias.

La ‘dirección efectiva de un operando’ que se denota por de es el lugar en el que se encuentra almacenado un operando. Estadirección no tiene por qué ser una posición de memoria. Existen modos de direccionamiento en los que la dirección efectiva deun operando es un registro de propósito general.

La instrucción de la que se obtienen los datos necesarios para calcular de se denota por inst, la dirección de memoria a partirde la cual está almacenada es @inst, y los diferentes campos de esta instrucción se denotan por instc1, ..., instcn. Por camposse entienden aquellos bits que forman parte de la instrucción y que codifican los diferentes elementos necesarios para el cálculode la dirección efectiva.

Cuando el campo instci codifica uno de los registros de propósito general, dicho registro se denota por Rci. La expresiónMEM[n] denota el contenido de memoria almacenado a partir de la posición n. La acción de modificar el contenido del registroR con el dato d se denota R← d.

A continuación se estudian en detalle los modos de direccionamiento disponibles en la arquitectura IA-32 así como su sintaxis enensamblador. Para cada uno de ellos se especifica la fórmula utilizada para obtener la dirección efectiva del operando y su valor.

7.2. Modos del direccionamiento de la arquitectura IA-32

Tal y como se ha visto en la sección 5.3.3, los operandos de una instrucción se dividen en cuatro categorías: constantes, registros,direcciones de memoria y operandos implícitos. Excepto estos últimos, el resto se obtienen a través de diferentes modos dedireccionamiento. A continuación se presentan en orden creciente de complejidad para finalmente comparar todos ellos con elmás complejo.

7.2.1. Modo inmediato

Es el modo de direccionamiento utilizado para obtener operandos de tipo constante, es decir, aquellos que tienen el prefijo $ enensamblador. El operando está incluido en la propia instrucción. La expresión de su dirección efectiva se muestra en la ecuación7.2.

de = @inst + k

operando = MEM[@inst + k]

EQUATION 7.2: Dirección efectiva y operando del modo inmediato

Page 123: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

123 / 198

El valor k representa el número de bytes a partir de la dirección en la que está almacenada instrucción en la que se codifica laconstante. La figura 7.3 ilustra el funcionamiento de este modo de direccionamiento así como un ejemplo.

Figura 7.3: Acceso a operando con modo inmediato

El primer operando de la instrucción es la constante $3 que tal y como se ve en la figura, en lenguaje máquina se codifica enel último byte. Por tanto, la dirección efectiva del operando es de = @inst + 4. Cuando el procesador necesita este operando, loobtiene directamente de los bytes de la instrucción.

A pesar de que el sufijo de la instrucción indica que los operandos han de ser de 32 bits, el primer operando se codifica con unúnico byte. Esta aparente inconsistencia no es más que un mecanismo que utiliza el procesador para que el código máquina seamás compacto. Cuando en una instrucción se codifica un operando en modo inmediato se utilizan 1, 2 o 4 bytes dependiendo desu valor. En este ejemplo, como el valor es $3 sólo precisa un byte.

7.2.2. Modo registro

Es el modo de direccionamiento utilizado para obtener operandos almacenados en uno de los ocho registros de propósito general.La instrucción contiene un campo instc1 de 3 bits que codifica los ocho posibles registros. La expresión de la dirección efectivay el valor del operando se muestran en la ecuación 7.3.

de = instc1

operando = Rc1

EQUATION 7.3: Dirección efectiva y operando del modo registro

La dirección efectiva del operando, en este caso, no es una dirección de memoria, sino la de uno de los registros de propósitogeneral. La figura 7.4 muestra el funcionamiento de este modo de direccionamiento y un ejemplo.

Page 124: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

124 / 198

Figura 7.4: Acceso a operando con modo registro

En la figura, el código de operación 0x89 no sólo indica que se realiza una operación de mover, sino que el primer operando esde tipo registro. El nombre del registro está codificado en el segundo byte. También en este byte, se codifica el tipo del segundooperando, que es igualmente de tipo registro. Para ello se utiliza el campo R/M del byte ModR/M.

7.2.3. Modo absoluto

Los modos de direccionamiento restantes se refieren todos ellos a operandos almacenados en memoria y se diferencian en loscálculos para obtener la dirección efectiva de.

En este modo de direccionamiento la dirección efectiva corresponde con una dirección de memoria y forma parte de los bytesque codifican la instrucción. En otras palabras, la propia instrucción, en su codificación incluye una dirección de la que obteneruno de sus operandos. La expresión de la dirección efectiva y el valor del operando se muestran en la ecuación 7.4.

de = MEM[@inst + k]operando = MEM[MEM[@inst + k]]

EQUATION 7.4: Dirección efectiva y operando del modo absoluto

Como la instrucción contiene la dirección efectiva, ésta está contenida en memoria desplazada k bytes con respecto a la dirección@inst. El operando está en memoria en la posición que indica de, de ahí la doble expresión MEM[]. La figura 7.5 muestra elfuncionamiento de este modo de direccionamiento.

Page 125: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

125 / 198

Figura 7.5: Acceso a operando con modo absoluto

Como muestra la figura, la dirección de memoria ocupa 4 de los bytes que codifican la instrucción. En el ejemplo que se muestra,la dirección es 0x0000059A pues los datos se almacenan en little endian. La representación en ensamblador de este modode direccionamiento es mediante una etiqueta. El ensamblador asigna a cada una de ellas un valor, y cuando se utiliza en unainstrucción se reemplaza el símbolo por el valor de su dirección de memoria.

7.2.4. Modo registro indirecto

El modo registro indirecto accede a un operando en memoria utilizando como dirección el valor contenido en uno de los registrosde propósito general. La palabra ‘indirecto’ hace referencia a que primero se obtiene el valor del registro y luego se utiliza dichovalor como dirección de memoria. La expresión de la dirección efectiva y el valor del operando se muestran en la ecuación 7.5.

de = Rc1

operando = MEM[Rc1]

EQUATION 7.5: Dirección efectiva y operando del modo indirecto

Para codificar este modo de direccionamiento sólo es preciso incluir el código del registro de propósito general a utilizar, portanto con 3 bits es suficiente. La responsabilidad de que en el registro utilizado para la indirección esté contenida una dirección dememoria correcta recae totalmente en el programador. La figura 7.6 ilustra el funcionamiento de este modo de direccionamientoasí como un ejemplo.

Page 126: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

126 / 198

Figura 7.6: Acceso a operando con modo registro indirecto

Tal y como muestra la figura, la sintaxis para denotar este modo de direccionamiento en una instrucción es con el nombre delregistro escrito entre paréntesis. El operando se obtiene de memoria mediante la dirección almacenada en el registro. La principalventaja de este modo de direccionamiento es que, al estar almacenada la dirección en un registro, esta se puede manipular conlas operaciones aritméticas que ofrece el procesador como cualquier otro dato.

Por ejemplo, la instrucción MOV (%esp),%eax carga en el registro%eax el valor almacenado en la cima de la pila. Lainstrucción es correcta porque el registro%esp contiene la dirección de memoria de la cima de la pila.

Considérese la secuencia de instrucciones del ejemplo 7.2. La primera instrucción simplemente copia el valor del puntero depila en el registro%eax. La siguiente instrucción suma la constante $4 al valor almacenado en la cima de la pila. La instrucciónnecesita el sufijo de tamaño porque el segundo operando es un registro indirecto, con lo que especifica la dirección de memoriadel operando, pero no su tamaño.

Ejemplo 7.2 Acceso a los elementos de la pila con el modo registro indirecto

mov %esp, %eaxaddl $4, (%eax)add $4, %eaxaddl $4, (%eax)

La instrucción add $4,%eaxmuestra como una dirección de memoria se puede manipular como un dato numérico. Al sumarle$4 el nuevo valor obtenido es la dirección de memoria del elemento almacenado en la pila justo debajo de la cima. La últimainstrucción suma la constante $4 al operando almacenado en memoria en la dirección contenida en el registro%eax, o lo que eslo mismo, al dato almacenado debajo de la cima de la pila.

En el ejemplo anterior, se ha manipulado el contenido de los datos almacenados en la pila sin modificar el puntero a su cima.Esto es posible gracias a que se han hecho los cálculos con una dirección de memoria que es una copia del puntero a la cima.

El modo registro indirecto se puede utilizar para acceder a cualquier dato en memoria. En el ejemplo 7.3 se muestra una secuenciade instrucciones que acceden a elementos de una tabla de datos de 16 bits almacenados a partir de la dirección de memoriarepresentada por la etiqueta tabla.

Page 127: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

127 / 198

Ejemplo 7.3 Acceso a los elementos de una tabla con el modo registro indirecto

mov $tabla, %eaxmov (%eax), %bxadd $2, %eaxmov (%eax), %cxadd $6, %eaxmov (%eax), %dx

La primera instrucción almacena en el registro%eax la dirección de memoria representada por la etiqueta tabla. El valorexacto que se carga en el registro es imposible saberlo de antemano, pues depende de dónde en memoria estén almacenados losdatos, pero igualmente se puede utilizar con los modos de direccionamiento.

La segunda instrucción accede al primer elemento de la tabla con el modo registro indirecto. El operando destino es el registro%-bx que por tanto, fija el tamaño de dato a ser transferido a 16 bits y no es necesario el sufijo de tamaño. La siguiente instrucciónsuma la constante $2 al registro%eax y se accede de nuevo a un elemento de la tabla mediante registro indirecto. En este casose almacena en el registro%cx el número de 16 bits almacenado en segunda posición. La instrucción add $6,%eax hace queel registro contenga la dirección del elemento en la quinta posición, o lo que es equivalente, con índice 4. La última instrucciónaccede a este elemento de la tabla y lo almacena en%dx.

7.2.5. Modo auto-incremento

El funcionamiento del modo auto-incremento es similar al modo registro indirecto, con la salvedad de que el registro, tras serutilizado para el acceso a memoria, incrementa su valor en una constante. La expresión de la dirección efectiva y el valor deloperando se muestran en la ecuación 7.6

de = Rc1

operando = MEM[Rc1]Rc1 ← Rc1 +4

EQUATION 7.6: Dirección efectiva y operando del modo auto-incremento

El efecto de la modificación del valor contenido en el registro es que la dirección pasa ahora a apuntar a una posición de memoriacuatro bytes más alta que el valor anterior. En principio, cualquier registro de propósito general puede ser utilizado, pero en elcaso concreto de la arquitectura IA-32, este modo únicamente se utiliza en la instrucción POP y con el registro%esp. La figura7.7 ilustra el funcionamiento de este modo de direccionamiento así como un ejemplo de la instrucción POP.

Page 128: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

128 / 198

Figura 7.7: Acceso a operando con modo auto-incremento

Al tratarse de la única instrucción de la arquitectura IA-32 que utiliza este modo de direccionamiento y que únicamente se utilizael registro%esp, la codificación en la instrucción de este modo de direccionamiento es un caso especial, pues está implícitaen el código de operación. El byte con valor 0x58 no sólo codifica la operación POP sino también la utilización del modoauto-incremento con el registro%esp para obtener el dato a almacenar.

El efecto de este modo de direccionamiento corresponde con el comportamiento de la instrucción POP. El operando implícito esel dato de la cima de la pila que se obtiene mediante la dirección de memoria almacenada en%esp. Este operando se almacenadonde indica el único operando explícito de la instrucción, y a continuación se incrementa el valor de%esp de forma automáticaen 4 unidades. Como consecuencia, el puntero de pila apunta a la nueva cima.

7.2.6. Modo auto-decremento

El modo auto-decremento es similar al auto-incremento pues realiza una indirección y modifica el registro utilizado, pero lamodificación de la dirección se realiza antes de acceder a memoria. La funcionalidad de este modo de direccionamiento se puedeconsiderar complementaria a la anterior. La expresión de la dirección efectiva y el valor del operando se muestran en la ecuación7.7

de = Rc1−4operando = MEM[Rc1−4]

Rc1 ← Rc1−4

EQUATION 7.7: Dirección efectiva y operando del modo auto-decremento

La dirección efectiva no está directamente contenida en el registro especificado, sino que previamente se resta la constante 4 asu valor y se accede a memoria con el valor resultante. Además, este valor, tras acceder a memoria, se almacena de nuevo enel registro. En principio cualquier registro de propósito general puede utilizarse para este modo de direccionamiento, pero enel caso de la arquitectura IA-32, este modo únicamente se utiliza en la instrucción PUSH y con el registro%esp. La figura 7.8ilustra el funcionamiento de este modo de direccionamiento así como un ejemplo de la instrucción PUSH.

Page 129: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

129 / 198

Figura 7.8: Acceso a operando con modo auto-decremento

Al igual que en el caso del modo auto-incremento, al ser PUSH la única instrucción que utiliza este modo en la arquitecturaIA-32, su codificación está implícita en el código de operación 0x6A. El operando implícito, por tanto es la dirección de la nuevacima en la que almacenar el valor dado como operando explícito y que se obtiene restando 4 del registro%esp.

7.2.7. Modo base + desplazamiento

El modo de direccionamiento base + desplazamiento obtiene la dirección efectiva del operando mediante la utilización de doselementos. Este es el primer ejemplo en el que el procesador, como paso previo para la obtención de los operandos, obtiene másde un dato de la instrucción y lo utiliza para calcular la dirección efectiva. La expresión de la dirección efectiva y el valor deloperando se muestran en la ecuación 7.8.

de = Rc1 +instc2

operando = MEM[Rc1 +instc2]

EQUATION 7.8: Dirección efectiva y operando del modo base + desplazamiento

En este modo, la dirección efectiva no está contenida en ningún lugar, sino que es el resultado de la suma del contenido de unregistro y de un valor almacenado como parte de la instrucción. El procesador obtiene estos dos valores, los suma, y el resultadolo utiliza para acceder a memoria y obtener el operando. El nombre de este modo se deriva de que al registro utilizado se le conocecomo el nombre de ‘base’ mientras que el valor numérico adicional se conoce como ‘desplazamiento’. Como la operación quese realiza entre ambos es la suma, se puede considerar que la dirección efectiva del operando se obtiene partiendo de un registrobase cuyo valor se desplaza tanto como indica la constante.

La sintaxis para especificar este modo de direccionamiento tiene dos posibles formatos. El primero consiste en escribir el nombredel registro entre paréntesis precedido de una constante entera sin prefijo alguno, como por ejemplo la instrucción INCL 12-(%ecx). La constante puede ser escrita en cualquiera de los formatos permitidos por el ensamblador: decimal, binario, octal,hexadecimal o letra.

El segundo formato permitido consiste en escribir el nombre del registro entre paréntesis precedido por el nombre de una etiquetapreviamente definida, como por ejemplo la instrucción SUB%eax, dato(%ecx). El valor dato hace referencia a la direcciónde memoria en la que esta etiqueta ha sido definida, por lo que la dirección efectiva se obtiene sumando la dirección de la etiquetacon el valor contenido en el registro base. En los programas ensamblador se utilizan ambas notaciones de forma muy frecuente.La figura 7.9 ilustra el funcionamiento de este modo de direccionamiento así como dos ejemplos.

Page 130: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

130 / 198

Figura 7.9: Acceso a operando con modo base + desplazamiento

La instrucción ADD%eax, 16(%ebx) utiliza el primer formato de este modo en su segundo operando. La instrucción codificael desplazamiento con sólo 8 bits al tener un valor entre -128 y 127. El byte ModR/M con valor 0x43 codifica que el modode direccionamiento del primer operando es registro y que el del segundo es base + desplazamiento con el registro%ebx y unaconstante de 8 bits.

La instrucción ADD%eax, contador(%ecx) tiene una codificación de 6 bytes. Los cuatro últimos codifican la dirección dememoria que representa la etiqueta contador. El byte ModR/M con valor 0x81 en este caso codifica el modo de direcciona-miento del primer operando que es registro y que el del segundo es con registro base%ebx y desplazamiento de 32 bits.

Este modo de direccionamiento ofrece un mecanismo muy eficiente para acceder a tablas de elementos. Supóngase que se hadefinido una tabla de números enteros de 32 bits y se escribe el código que se muestra en el ejemplo 7.4.

Page 131: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

131 / 198

Ejemplo 7.4 Acceso a una tabla de enteros con modo base + desplazamiento

.datatabla: .int 12, 32, -34, -1, 1232, 435

.text

.global mainmain:

...mov $0, %ebxmov $0, %ecxADD tabla(%ebx), %ecxADD $4, %ebxADD tabla(%ebx), %ecxADD $4, %ebxADD tabla(%ebx), %ecxADD $4, %ebx...

Los enteros se almacenan a partir de la posición de memoria que representa la etiqueta tabla. Las dos primeras instruccionescargan el valor 0 en los registros%ebx y%ecx. Las siguientes instrucciones suman el valor de los tres primeros de la tabla ydepositan el resultado en el registro%ecx. Para ello, el registro%ebx contiene el valor que sumado a la dirección de tabla seobtiene la dirección de los sucesivos elementos. La instrucción ADD tabla(%ebx),%ecx se repite sin modificación algunay accede a elementos sucesivos porque el registro base va cambiando su valor. Este tipo de instrucciones son muy eficientes si sequiere procesar todos los elementos de una tabla, pues basta con escribir un bucle que vaya incrementando, en este caso, el valordel registro%ebx.

La utilización de constantes como desplazamiento se utiliza generalmente para acceder a elementos almacenados en posicionesalrededor de una dirección dada que se almacena en el registro base. Supóngase que el registro%edx contiene la dirección de me-moria a partir de la cual están almacenados, por este orden, dos números enteros y cuatro letras ASCII. El código que se muestraen la ejemplo 7.5 accede a los enteros y las cuatro letras con el registro%edx como base y con diferentes desplazamientos.

Ejemplo 7.5 Definición y acceso a una tabla de enteros

.data

.int 34dato: .int 12, 24

.ascii "abcd"

.text

.global mainmain:

...mov $dato, %edxmov 0(%edx), %ecxadd 4(%edx), %ecxmov 8(%edx), %ahmov 9(%edx), %almov 10(%edx), %bhmov 11(%edx), %bladd -4(%edx), %ecx...

La primera instrucción almacena en%edx la dirección de memoria que representa la etiqueta dato. En la segunda instrucciónse utiliza el modo de direccionamiento base + desplazamiento pero con un desplazamiento igual a cero. El entero con valor 12se almacena en el registro%ecx. Esta instrucción pone de manifiesto que el modo base + desplazamiento con un desplazamientoigual a cero, es equivalente al modo registro indirecto.

La siguiente instrucción add 4(%edx),%ecx suma el valor del segundo entero al registro%ecx. El desplazamiento tieneel valor 4 debido a que los enteros almacenados a partir de la etiqueta son de 4 bytes. La siguiente instrucción accede a la

Page 132: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

132 / 198

primera letra y la almacena en el registro de 8 bits%ah. En este caso el desplazamiento es 8 porque las letras están almacenadasen la posición siguiente a la del último byte del último entero de la definición anterior. Las siguientes instrucciones cargan lassiguientes letras en los registros de 8 bits%al,%bh y%bl.

En este modo de direccionamiento, el número que precede al registro entre paréntesis es un entero, y por tanto puede tener valornegativo. La última instrucción muestra un ejemplo de este caso. De igual forma que se acceden a posiciones a continuación de laespecificada por una etiqueta, también se puede acceder a posiciones previas mediante desplazamientos negativos. El procesadorsuma este desplazamiento al valor del registro y accede a esa posición de memoria. Con las definiciones del ejemplo la instrucciónestá sumando al registro%ecx el número 34 almacenado justo antes de la etiqueta.

7.2.8. Modo base + índice

El modo de direccionamiento base + índice es similar al anterior puesto que el procesador obtiene la dirección efectiva sumandode nuevo dos números, pero la diferencia es que ambos números se obtienen de registros de propósito general. La expresión dela dirección efectiva y el valor del operando se muestran en la ecuación 7.9.

de = Rc1 +Rc2

operando = MEM[Rc1 +Rc2]

EQUATION 7.9: Dirección efectiva y operando del modo base + índice

Al igual que en caso del modo de direccionamiento anterior, la dirección efectiva no tiene por qué encontrarse en ningún registrosino que se obtiene sumando el valor contenido en los dos registros especificados. No existe restricción alguna sobre los valoresque contienen los registros, el procesador realiza la suma y obtiene el operando de la posición de memoria obtenida comoresultado. La sintaxis para especificar este modo de direccionamiento es mediante dos registros separados por una coma y entreparéntesis, por ejemplo CMPL $32, (%eax,%esi).

A pesar de que este modo se denomina base + índice, los dos registros especificados son idénticos a todos los efectos, conlo que cualquiera de los dos puede ser el registro base o el índice. La figura 7.10 ilustra el funcionamiento de este modo dedireccionamiento así como un ejemplo.

Figura 7.10: Acceso a operando con modo base + índice

La dirección efectiva se obtiene sumando los registros%ebx y%edi que previamente deben tener los valores pertinentes paraque la dirección de memoria resultante sea la correcta. Supóngase una tabla con 100 elementos, cada uno de ellos, a su vez esuna tabla de 5 enteros. Para acceder a un número se precisan dos índices, el primero para seleccionar uno de los 100 elementos,

Page 133: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

133 / 198

y el segundo para seleccionar uno de los 5 posibles enteros. Se quiere acceder a los cinco números del elemento tabla[32]almacenados a partir de la dirección de memoria contenida en el registro%eax. El ejemplo 7.6 muestra cómo acceder a estoselementos utilizando el modo de direccionamiento base + índice.

Ejemplo 7.6 Acceso a los enteros de un elemento de una tabla

....mov $0, %ebxmov (%eax, %ebx), %ecxadd $4, %ebxadd (%eax, %ebx), %ecxadd $4, %ebxadd (%eax, %ebx), %ecxadd $4, %ebxadd (%eax, %ebx), %ecxadd $4, %ebxadd (%eax, %ebx), %ecx...

La primera instrucción carga el valor cero en%ebx. A continuación se accede al primer entero del elemento de la tabla sumandola dirección a partir de donde están almacenados, que está contenida en%eax y el valor en%ebx. Como este último registrotiene el valor cero, el acceso es idéntico al obtenido si se utiliza el modo registro indirecto.

A continuación se suma 4 al registro%ebx y se accede de nuevo con el mismo modo en este caso para sumar el contenido enmemoria al registro%ecx. Tras ejecutar esta instrucción en%ecx se obtiene la suma de los dos primeros elementos. Mediantesucesivos incrementos del registro%ebx y luego accediendo a los elementos con el modo base + índice se calcula la suma de loscinco números en el registro%ecx.

La misma secuencia de instrucciones tendría un efecto idéntico si se intercambian los nombres de los registros en el paréntesisque especifica el modo base + índice.

7.2.9. Modo índice escalado + desplazamiento

En este modo de direccionamiento toman parte tres elementos de la instrucción para obtener la dirección efectiva del operando.Un registro, denominado el índice, ofrece un valor que se multiplica por un factor de escala especificado por una constante, y elresultado se suma a una segunda constante entera denominada desplazamiento. El factor de escala puede tener únicamente losvalores 1, 2, 4 y 8. La expresión de la dirección efectiva y el valor del operando se muestran en la ecuación 7.10.

de = (Rc1 ∗instc2)+instc3

operando = MEM[(Rc1 ∗instc2)+instc3]instc2 ∈ {1,2,4,8}

EQUATION 7.10: Dirección efectiva y operando del modo índice escalado + desplazamiento

La característica más importante de este modo de direccionamiento es el producto entre el registro índice y la escala. Este últimofactor, en lugar de ser un número entero, tan sólo puede una de las cuatro primeras potencias de dos. La razón para esta restricciónes que la operación de multiplicación de enteros es extremadamente costosa en tiempo como para que forme parte del cálculode la dirección efectiva. En cambio, la multiplicación por estas potencias de dos es muy eficiente pues el resultado se obtienemediante el desplazamiento del valor del registro. Si el factor de escala utilizado es 1, este modo de direccionamiento es idénticoal modo base + desplazamiento.

La sintaxis de este modo es ligeramente contra-intuitiva, pues se especifica el registro índice y el factor de escala separadospor coma pero precedidos por una coma adicional, entre paréntesis y este a su vez precedido por el entero que codifica eldesplazamiento. La figura 7.11 ilustra el funcionamiento de este modo de direccionamiento así como un ejemplo.

Page 134: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

134 / 198

Figura 7.11: Acceso a operando con modo índice escalado + desplazamiento

La dirección efectiva del segundo operando de la instrucción de la figura se obtiene multiplicando el contenido de%eax por elfactor de escala 8 y sumando el desplazamiento. Al igual que en el caso del modo base + desplazamiento, este último elementopuede ser un número entero o una etiqueta previamente definida. Considérese el ejemplo de una tabla de enteros de 64 bitsalmacenados a partir de la etiqueta coeficientes. El ejemplo 7.7 muestra la definición y manipulación de estos datos con elmodo índice escalado + desplazamiento.

Page 135: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

135 / 198

Ejemplo 7.7 Acceso a una tabla de enteros de 64 bits con modo índice escalado + desplazamiento

.datacoeficientes:

.quad 21, 34, 56, 98

.text

.global mainmain:

...mov $0, %eaxmov coeficientes(, %eax, 8), %ebxinc %eaxadd coeficientes(, %eax, 8), %ebxinc %eaxadd coeficientes(, %eax, 8), %ebxinc %eaxadd coeficientes(, %eax, 8), %ebx...

Los números definidos por la directiva .quad son de 64 bits y por tanto ocupan 8 bytes. Tras cargar el valor 0 en el registro%e-ax, las siguientes instrucciones acceden a los números de forma sucesiva utilizando este registro como índice. La multiplicacióndel registro índice por el factor de escala 8 que coincide con el tamaño de los datos hace que el índice coincida con el valor quese utilizaría en un lenguaje de alto nivel como Java para acceder a los números: coeficientes[3] se accede mediante laexpresión coeficientes(,%eax, 8) si%eax contiene el valor 3.

7.2.10. Modo base + índice escalado + desplazamiento

Este modo de direccionamiento es el más complejo que ofrece el procesador y se puede considerar como la combinación de losmodos base + desplazamiento e índice escalado + desplazamiento. La dirección efectiva se calcula sumando tres números: eldesplazamiento, el contenido de un registro base y la multiplicación de un registro índice por un factor de escala que puede tenerlos valores 1, 2, 4 u 8. La expresión de la dirección efectiva y el valor del operando se muestran en la ecuación 7.11.

de = Rc1 +(Rc2 ∗instc3)+instc4

operando = MEM[Rc1 +(Rc2 ∗instc3)+instc4]instc3 ∈ {1,2,4,8}

EQUATION 7.11: Dirección efectiva y operando del modo base + índice escalado + desplazamiento

Este modo de direccionamiento precisa cuatro elementos que están contenidos en la codificación de la instrucción. El campo quemás espacio requiere es el desplazamiento que puede ser un valor entero o el nombre de una etiqueta previamente definida, porlo que se precisan 32 bits. El factor de escala, al poder tomar únicamente cuatro valores, se puede codificar con 2 bits.

La sintaxis de este modo es también una combinación de los anteriores. Entre paréntesis se escribe el registro base, el registroíndice y el factor de escala, por este orden y separados por comas. El paréntesis va precedido del valor del desplazamiento. Lafigura 7.12 ilustra el funcionamiento de este modo de direccionamiento así como un ejemplo.

Page 136: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

136 / 198

Figura 7.12: Acceso a operando con modo base + índice escalado + desplazamiento

El efecto de este modo de direccionamiento es que la dirección efectiva se obtiene sumando un registro, una constante (eldesplazamiento) y un segundo registro susceptible de ser escalado. Al igual que en el modo índice escalado + desplazamiento,la multiplicación por la escala se realiza desplazando el operando cero, una, dos o tres posiciones hacia su bit de más peso. Aligual que en el resto de modos que utilizan un desplazamiento, este puede ser un número entero o una etiqueta previamentedefinida. En la instrucción DIVL 4(%ecx,%edi, 4) mostrada en la figura, la dirección efectiva del operando es 4 +%ecx+ (%edi * 4), por lo que se asume que el registro%ecx contiene el valor de una dirección con respecto a la cual se accedeal operando. En la instrucción INCB contador(%ecx,%edi, 4) el desplazamiento es una dirección de memoria en basede la cual se obtiene la dirección efectiva del operando.

Como ejemplo de utilización de este modo de direccionamiento considérese que se ha definido una tabla de 10 enteros en Java apartir de la posición de memoria con etiqueta num. A continuación se quiere acceder al elemento de la tabla con índice almace-nado en el registro%ecx e incrementar su valor en una unidad. El código mostrado en el ejemplo 7.8 muestra las instruccionesnecesarias para esta operación.

Page 137: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

137 / 198

Ejemplo 7.8 Acceso a una tabla de enteros en Java con modo base + índice escalado + desplazamiento

.datanum: .int 10, -1, 32, 345, -3556, 4, 21, 23, 15, 6543, 23

.text

.global mainmain:

...mov $4, %ebxincl num(%ebx, %ecx, 4)...

Como Java almacena el tamaño de una tabla en los cuatro primeros bytes, la dirección del elemento con índice en%ecx seobtiene mediante la expresión num + 4 + (%ecx * 4) que se puede calcular de forma eficiente utilizando el modo base + índiceescalado + desplazamiento. Si se quisiese incrementar el valor de todos los elementos de la tabla se puede escribir un bucle queincremente el valor del registro%ecx desde cero hasta el tamaño de la tabla menos uno e incremente cada uno de ellos con unainstrucción idéntica a la del ejemplo.

7.2.11. Utilización de los modos de direccionamiento

Se han estudiado los modos de direccionamiento que ofrece el procesador como mecanismo eficiente de acceso a memoria. Notodos los cálculos de la dirección efectiva de un operando pueden realizarse en una sola instrucción por medio de estos modos,tan sólo aquellos que requieran el tipo de operaciones que ofrece alguno de ellos. Los modos de direccionamiento son por tanto,un recurso que el procesador ofrece para ganar eficiencia en la ejecución de programas, pero que de ninguna forma limita laforma de obtener la dirección efectiva.

A la hora de programar en ensamblador y acceder a datos en memoria, la técnica para acceder a los datos es tener en cuenta quéoperaciones se deben realizar para obtener su dirección, y si éstas pueden ser incluidas en una misma instrucción como modo dedireccionamiento mejor que realizar estos cálculos con instrucciones máquina adicionales.

Supóngase que se define una matriz de enteros con m filas y n columnas a partir de la posición representada por la etiqueta matr-iz. Los valores m y n son enteros y están almacenados en memoria con etiquetas del mismo nombre. Las matrices se almacenanen memoria utilizando múltiples estrategias. Las dos más comunes son por filas y por columnas. En el primer formato, sealmacenan los elementos de una fila en posiciones contiguas de memoria y a continuación los de la siguiente fila. En el segundoformato, los elementos de una columna ocupan posiciones de memoria consecutivas, y a continuación se almacena la siguientecolumna. Supóngase que los elementos de esta matriz están almacenados por filas. La figura 7.13 muestra la distribución de losdatos en memoria mediante su definición en ensamblador. Cada posición de la matriz contiene un número formado por el númerode fila seguido del número de columna.

Figura 7.13: Definición de una matriz de enteros almacenada por filas

Para acceder a un elemento de la matriz se precisan dos índices (i, j), donde 0≤ i < m y 0≤ j < n. Dados los índices (i, j), laexpresión de la dirección efectiva de este elemento según la definición de la figura 7.13 se muestra en la ecuación 7.12.

de = $matriz+(i∗n∗4)+( j ∗4)

EQUATION 7.12: Dirección de un elemento en una matriz de enteros

Page 138: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

138 / 198

Supóngase que se tiene que acceder al elemento en la posición que indican los registros%eax y%ebx para incrementar en unaunidad su valor mediante la instrucción INC. Dada la funcionalidad ofrecida en los modos de direccionamiento, no es posibleacceder al elemento con una única instrucción, pues el cálculo de su dirección efectiva requiere operaciones no contempladas.

Pero una porción de la ecuación 7.12 sí puede ser calculada por el modo de direccionamiento base + índice escalado + despla-zamiento. Como desplazamiento se utiliza el valor de la etiqueta matriz, la segunda multiplicación se puede ejecutar como uníndice escalado, por lo que tan sólo es preciso obtener el resultado de (i * n * 4) y almacenarlo en un registro. El ejemplo 7.9muestra una posible secuencia de instrucciones para acceder e incrementar el elemento.

Ejemplo 7.9 Instrucciones para incrementar un elemento de una matriz de enteros

...mull nsal $2, %eaxincl matriz(%eax, %ebx, 4)...

La instrucción mull n multiplica el número de columnas por el índice que indica el número de fila. Tal y como funciona estainstrucción, al especificar un operando de 32 bits mediante el sufijo, resultado se almacena en el registro de 64 bits obtenidoal concatenar%edx:%eax. Se asume que el resultado no sobrepasa los 32 bits de%eax. A continuación la instrucción sal$2,%eax desplaza el registro dos posiciones a su izquierda que equivale a multiplicar por cuatro. Con esto se obtiene en%eaxel término de la ecuación 7.12 que falta para poder utilizar el modo base + índice escalado + desplazamiento tal y como muestrala instrucción incl matriz(%eax,%ebx, 4).

Como efectos colaterales de este cálculo se ha perdido el valor inicial del índice almacenado en%eax así como el valor delregistro%edx ambos modificados por la instrucción de multiplicación. A modo de comparación, el ejemplo 7.10 muestra unasecuencia alternativa de instrucciones para realizar la misma operación pero que únicamente utiliza el modo registro indirecto.

Ejemplo 7.10 Instrucciones para incrementar un elemento de una matriz de enteros utilizando el modo registro indirecto

...mull nsal $2, %eaxsal $2, %ebxadd %ebx, %eaxadd $matrix, %eaxincl (%eax)...

Las instrucciones adicionales realizan los cálculos equivalentes al modo base + índice escalado + desplazamiento solo queutilizando instrucciones máquina del procesador. El resultado de esta secuencia es casi idéntico al anterior (en este caso se haperdido también el valor dado en el%ebx) pero se ha utilizado un número muy superior de instrucciones, con lo que su ejecuciónes mucho menos eficiente.

Este ejemplo pone de manifiesto cómo el acceso a los operandos puede realizarse de múltiples formas, pero para obtener unaejecución eficiente y código compacto debe seleccionarse aquella que haga uso de los modos de direccionamiento ofrecidos porel procesador.

7.3. Hardware para el cálculo de la dirección efectiva

Una vez estudiados los modos de direccionamiento que ofrece el procesador se puede intuir el tipo de circuito digital utilizadopara calcular la dirección efectiva de un operando almacenado en memoria. La figura 7.14 muestra una posible implementación.

Page 139: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

139 / 198

Figura 7.14: Circuito para el cálculo de la dirección efectiva

Este circuito calcula la dirección efectiva para los modos de direccionamiento cuyo operando se encuentra en memoria, es decir,todos excepto inmediato y registro. De los bits que codifican la instrucción se obtienen los cuatro posibles elementos el cálculode la dirección efectiva y mediante la utilización de las señales de control b, i, e y d se activa la participación de cada una deellos. Por ejemplo, el modo índice escalado + desplazamiento requiere que la señal i seleccione la entrada del multiplexor queprocede del banco de registros, la señal d seleccione el valor obtenido de la instrucción, y las dos señales restantes seleccionen laentrada constante de sus respectivos multiplexores.

7.4. Resumen de los modos de direccionamiento

Los modos de direccionamiento son los diferentes procedimientos que utiliza el procesador dentro de la ejecución de una ins-trucción para acceder a sus operandos. Las diferentes formas que permite la arquitectura IA-32 para acceder a sus operandos semuestran en la Tabla 7.1.

Modo dedireccionamiento Dirección efectiva Operando Condiciones adicionales

Inmediato @inst + k MEM[@inst + k]Registro instc1 Rc1Absoluto MEM[@inst + k] MEM[MEM[@inst + k]]Registro indirecto Rc1 MEM[Rc1]Auto-incremento Rc1 MEM[Rc1] Rc1← Rc1 +4Auto-decremento Rc1−4 MEM[Rc1−4] Rc1← Rc1−4Base + desplazamiento Rc1 +instc2 MEM[Rc1 +instc2]Base + índice Rc1 +Rc2 MEM[Rc1 +Rc2]Índice escalado +desplazamiento

(Rc1 ∗instc2)+instc3MEM[(Rc1 ∗instc2)+

instc3]instc2 ∈ {1,2,4,8}

Base + índice escalado +desplazamiento

Rc1 +(Rc2 ∗instc3)+instc4

MEM[Rc1 +(Rc2 ∗instc3)+instc4]

instc3 ∈ {1,2,4,8}

Tabla 7.1: Modos de direccionamiento de la arquitectura IA-32

7.5. Ejercicios

1. Asumiendo que los campos de una instrucción máquina son ci1, ci2, ci3, ci4,... escribir la fórmula del cálculo de la direcciónefectiva del operando y explicar su significado para los siguientes modos de direccionamiento: (Utilícese la notación (x)para denotar ‘el contenido de x’).

Page 140: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

140 / 198

a. Registro Indirecto:

b. Absoluto:

c. Base + Índice:

d. Base + Índice Escalado + Desplazamiento:

2. Supóngase que de todos los modos de direccionamiento de la arquitectura IA-32, los únicos que se pueden utilizar sonel modo registro, modo inmediato y el modo registro indirecto. Escribir la secuencia de instrucciones equivalentes a lassiguientes: (es decir que si se reemplaza la instrucción con las instrucciones de cada respuesta, el programa resultante esidéntico).

a.MOV matrix(%ebx), %eax

b.MOV table(, %ecx, 4), %eax

3. Un procesador llamado PDP-11 contiene en su juego de instrucciones dos modos de direccionamiento que no posee laarquitectura IA-32.

Modo Autoincremento Indirecto: Se representa como [Reg]++. El procesador accede a la posición de memoria conte-nida en el registro Reg y de dicha posición de memoria obtiene la dirección de memoria del operando. El registro Regqueda incrementado en cuatro unidades.

Modo Indexado Indirecto: Se representa como $desp[Reg]. El procesador accede a la posición de memoria resultantede sumar Reg y $desp, y de dicha posición de memoria obtiene la dirección de memoria del operando.

Especificar cómo deben traducirse las siguientes instrucciones del PDP-11 a instrucciones de la arquitectura IA-32 paraque la ejecución sea equivalente.

MOV [%eax]++,%ebx

MOV%ecx, $desp[%ecx]

4. Considerando el circuito de la figura 7.14, rellenar los valores de las señales b, i, e y d para cada uno de los modos dedireccionamientos de la siguiente tabla. La entrada constante de los multiplexores se selecciona poniendo la señal decontrol con valor idéntico a esta.

Modo dedireccionamiento Valor de b Valor de i Valor de e Valor de d

Absoluto 0 0 1 1Registro indirecto 1 0 1 0Base +desplazamiento 1 0 1 1

Base + índice 1 1 1 0Índice escalado +desplazamiento

0 1 0 1

Base + índiceescalado +desplazamiento

1 1 0 1

Page 141: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

141 / 198

Capítulo 8

Construcciones de alto nivel

Las aplicaciones que se ejecutan en un ordenador están generalmente programadas en alguno de los denominados lenguajes dealto nivel que los compiladores traducen a ejecutables que contienen secuencias de instrucciones máquina del procesador. Parafacilitar el desarrollo de estas aplicaciones se necesitan mecanismos adicionales tanto a nivel de procesador como de sistemaoperativo. Por ejemplo, la posibilidad de fragmentar el código en múltiples ficheros, gestión del acceso de símbolos en otrosficheros, etc.

En este capítulo se estudian los mecanismos que facilitan la traducción de programas en lenguajes de alto nivel a programasen ensamblador. Además de la fragmentación de código en múltiples ficheros, se estudia en detalle el procedimiento para lainvocación, paso de parámetros y ejecución de subrutinas, y la traducción de estructuras de control presentes en lenguajes deprogramación a lenguaje ensamblador.

8.1. Desarrollo de aplicaciones en múltiples ficheros

La funcionalidad que ofrece un procesador está basada en sus instrucciones máquina, órdenes muy simples para manipular datos.Pero para programar operaciones más complejas se precisa un lenguaje que sea más intuitivo y que abstraiga o esconda losdetalles de la arquitectura del procesador. A este tipo de lenguajes se les denomina ‘lenguajes de alto nivel’ por contraposiciónal lenguaje ensamblador cuya estructura y construcciones están directamente relacionadas con la arquitectura del procesador quelo ejecuta. La traducción de las operaciones en un lenguaje de alto nivel a secuencias de instrucciones máquina se lleva a cabopor el compilador.

Las principales limitaciones que se derivan del uso del lenguaje ensamblador son:

Las aplicaciones que contengan manejo de datos u operaciones complejas requieren secuencias de instrucciones extremada-mente largas, y por tanto, es muy fácil que se introduzcan errores.

El lenguaje ensamblador carece de tipos de datos. A pesar de que existen directivas para definir datos, su efecto no es másque almacenar una secuencia de bytes en memoria. El procesador accede a estos datos como una secuencia de bytes sininformación de tamaño ni de su tipo.

Las subrutinas ofrecen un mecanismo básico para ejecutar porciones de código de forma repetida y con diferentes datos, perono se realiza ningún tipo de comprobación de su correcta invocación.

Los lenguajes de alto nivel solventan estas limitaciones ofreciendo un conjunto de mecanismos para definir y manipular datos.Cada lenguaje tiene su propia sintaxis, o forma de escribir las órdenes, y su semántica, o cómo esas órdenes son traducidas asecuencias de instrucciones máquina.

Al conjunto de reglas para definir y manipular los tipos de datos en un lenguaje de alto nivel se le denomina el ‘sistema de tipos dedatos’. Aquellos lenguajes que estructuran sus datos en base a objetos que se crean a partir de una definición genérica denominada‘clase’ se les conoce como ‘lenguajes orientados a objeto’. Java, Smaltalk y C++ son algunos de los múltiples lenguajes con estacaracterística.

Page 142: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

142 / 198

El proceso de compilación de los programas escritos en lenguajes de alto nivel es similar al de traducción de lenguaje ensambladora lenguaje máquina. Dado un conjunto de ficheros escritos en el lenguaje de entrada, se produce un ejecutable que contiene latraducción de todos ellos a instrucciones máquina y definiciones de datos. La figura 8.1 muestra el procedimiento por el que dadoun conjunto de ficheros en lenguaje de alto nivel, el compilador obtiene un fichero ejecutable.

Figura 8.1: Compilación de un programa escrito en un lenguaje de alto nivel

El lenguaje de programación Java merece una mención especial, pues no sigue el patrón de traducción que se muestra en lafigura 8.1. Los programas se escriben en múltiples ficheros que contienen la definición de clases con sus campos y métodos. Elproceso de compilación no produce directamente un ejecutable sino un fichero con formato ‘class’ o ‘bytecode’. Este formatono corresponde con instrucciones máquina del procesador sino con instrucciones de lo que se conoce como ‘máquina virtual dejava’ o JVM (Java Virtual Machine).

La traducción a código de la JVM se realiza para garantizar la ‘portabilidad’ de un programa, es decir, que el fichero generado sepueda ejecutar sin modificaciones en cualquier procesador. La máquina virtual lee el código escrito en formato class y lo traducea instrucciones máquina del procesador sobre el que se ejecuta. Esta traducción se hace en el momento en el que se ejecuta unprograma. Por este motivo se dice que Java es un lenguaje parcialmente compilado y parcialmente interpretado. La compilacióntraduce el código inicial a formato bytecode que a su vez es interpretado en tiempo de ejecución por la máquina virtual.

Mediante la presencia de esta máquina virtual, se garantiza la compatibilidad de los programas Java en cualquier procesador.Para ello es preciso crear una máquina virtual diferente para cada uno de los procesadores existentes en el mercado. Una vezimplementada esta máquina virtual, todos los programas escritos en Java son ejecutables en esa plataforma.

Existen otro tipo de lenguajes de alto nivel que no precisan de un paso previo de compilación para obtener un ejecutable, sinoque se ejecutan directamente a través de un programa auxiliar denominado ‘intérprete’ cuyo cometido es similar al compiladorsólo que su tarea la hace justo en el instante que el programa debe ser ejecutado, y no como paso previo. A estos lenguajes dealto nivel se les denomina ‘interpretados’ pues el proceso que se lleva a cabo en el momento de la ejecución es una interpretacióndel código fuente y su traducción instantánea a código máquina. Perl, Python y TCL son algunos ejemplos de lenguajes deprogramación interpretados.

8.2. Programas en múltiples ficheros

La generación de un programa a partir de un conjunto de ficheros con código fuente procesándolos se realiza en dos pasos. Enel primero se traduce cada fichero por separado a código máquina. En el segundo paso denominado de ‘enlazado’ (ver sección1.5.2) se combinan las porciones de código generadas en el paso anterior y se crea el fichero ejecutable. Para ello se precisan dosmecanismos:

Política de acceso a los símbolos definidos en cada uno de los ficheros

Ejecución parcial de un fragmento de código en un fichero diferente al que se está ejecutando y su retorno al mismo punto unavez terminado.

Page 143: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

143 / 198

Cada fichero ensamblador contiene un conjunto de etiquetas que representan diferentes posiciones de memoria. Para que unprograma pueda ser fragmentado debe ser posible referirse a un símbolo definido en otro fichero. Por ejemplo, una instrucciónde salto debe poder especificar como destino un punto en el código de otro fichero.

Pero si una aplicación consta de múltiples ficheros cada uno de ellos con un número muy elevado de etiquetas definidas, tareascomo la ampliación de un programa se vuelven muy difíciles. Si los símbolos definidos en los ficheros son todos ellos globales,no se puede utilizar un nombre para una variable o una posición en el código que esté presente en otro fichero.

Para solucionar este problema se adopta la política de gestión opuesta para el ámbito de los símbolos. Todo símbolo definido enun fichero tiene como ámbito de validez únicamente el propio fichero a no ser que se especifique lo contrario con la directiva deensamblador .global. El ensamblador permite definir una etiqueta que coincide con el nombre de otra definida como global.En este caso, el símbolo local toma precedencia y por tanto el global no es accesible. De esta forma, cuando se escribe códigoensamblador en un fichero, en principio se puede utilizar cualquier nombre para una etiqueta.

En el primer paso de la traducción, todo símbolo que no esta definido en el fichero que se procesa se considera externo, y portanto su posición es desconocida. Es en el paso de entrelazado en el que los símbolos son todos conocidos y se pueden traducira sus correspondientes valores. El compilador incluye en cada fichero obtenido en el primer paso dos conjuntos de símbolos: elprimero corresponde con las etiquetas definidas en la zona de datos o de código que han sido declaradas globales, mientras queel segundo contiene aquellos que se utilizan pero cuya definición no se ha encontrado en el fichero. La figura 8.2 muestra unejemplo de programa escrito en dos ficheros en los que se producen referencias a símbolos externos.

Figura 8.2: Referencia a símbolos en dos ficheros

En la fase de entrelazado, para cada fichero, el compilador busca los símbolos externos en la lista de símbolos globales del restode ficheros. En el caso de que un símbolo externo no esté definido en ninguno de ellos se muestra un mensaje de error. Si dosficheros definen el mismo símbolo como global también se muestra un mensaje de error. En ambos casos no se produce ficheroejecutable.

Además de los símbolos contenidos en cada uno de los ficheros, en la fase de entrelazado el compilador dispone de códigoauxiliar en ficheros denominados ‘bibliotecas’ en los que se incluyen rutinas para realizar tareas comunes de cualquier programacomo lectura/escritura de datos a través de diferentes dispositivos (teclado, pantalla, ficheros, etc).

Otro aspecto que debe solventar el compilador para generar un ejecutable a partir de múltiples ficheros fuente es el de la ‘reubi-cación de código’. Al traducir el código ensamblador contenido en cada fichero, el código binario resultante se almacena a partirde la posición cero de memoria, pues no se sabe la posición exacta que ocupará a la hora de ejecutar. Pero cuando el código estáen múltiples ficheros, en la fase de entrelazado sólo el código de uno de ellos puede estar en la posición inicial, el resto debe serreubicado. La figura 8.3 muestra un ejemplo en el que el ejecutable se obtiene a partir de tres ficheros. El código de dos de ellosdebe ser reubicado.

Page 144: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

144 / 198

Figura 8.3: Reubicación de símbolos en la fase de entrelazado

La reubicación de código consiste en que toda instrucción que contenga en su codificación el valor de una dirección de memoria(por ejemplo, las que utilizan el modo de direccionamiento absoluto) deben ser modificadas para referirse a la posición dememoria tras la reubicación. El compilador recorre de nuevo las instrucciones máquina generadas y suma a toda dirección dememoria un factor de reubicación que corresponde con la dirección utilizada al comienzo del fichero.

Considérese la instrucción call metodo1 que invoca a la subrutina método definida en otro fichero. En la primera fasede compilación esta instrucción se traduce por el código 0xE8FCFFFFFF. Los cuatro últimos bytes denotan la dirección dememoria representada por la etiqueta método. En el ejecutable obtenido, el código de esta instrucción pasa a ser 0xE8FA000-000 que conserva el primer byte que corresponde con el código de operación pero cambia los cuatro últimos bytes que codificanla dirección de memoria.

8.3. Traducción de construcciones de alto nivel a ensamblador

Las construcciones que ofrecen los lenguajes de alto nivel como Java para escribir programas distan mucho de la funcionalidadofrecida por el lenguaje máquina del procesador. Por ejemplo, en Java se permite ejecutar una porción de código de formaiterativa mediante las construcciones for o while hasta que una condición se deje de cumplir. El compilador es el encargadode producir el código ensamblador tal que su ejecución sea equivalente a la especificada en el lenguaje Java.

A continuación se muestra cómo la funcionalidad ofrecida por el procesador es suficiente para traducir estas construcciones asecuencias de instrucciones ensamblador con idéntico significado.

8.3.1. Traducción de un if/then/else

La figura 8.4 muestra las tres partes de las que consta un bloque if/then/else. La palabra reservada if va seguida de una expresiónbooleana entre paréntesis. A continuación entre llaves una primera porción de código que puede ir seguida opcionalmente de unasegunda porción también entre llaves y con el prefijo else.

Page 145: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

145 / 198

if (expresión booleana) {Bloque A

} else {Bloque B

}

Figura 8.4: Estructura de un if/then/else

Lo más importante para traducir un bloque a ensamblador es saber su significado o semántica. La semántica del bloque if/then/elsees que se evalua la expresión booleana y si el resultado es verdadero se ejecuta el bloque A de código y se ignora el bloque B, ysi es falsa, se ignora el bloque A y se ejecuta el bloque B.

El elemento clave para traducir esta construcción a ensamblador es la instrucción de salto condicional. Este tipo de instruccionespermiten saltar a un destino si una condición es cierta o seguir la secuencia de ejecución en caso de que sea falsa. Lo único quese necesita es traducir la expresión booleana de alto nivel a una condición que pueda ser comprobada por una de las instruccionesde salto condicional ofrecida por el procesador. Supóngase que la expresión es falsa si el resultado de la evaluación es cero ycierta en caso contrario. Además, tras ejecutar las instrucciones de evaluación, el resultado se almacena en%eax. En la figura8.5 se muestra la estructura genérica en lenguaje ensamblador resultante de traducir un if/then/else en este supuesto.

... # Evaluar la expresión booleana

... # Resultado en %eaxcmp $0, %eaxje bloqueb... # Traducción del bloque A... # Fin del bloque Ajmp finifthenelse

bloqueb: # Traducción del bloque B...... # Fin del bloque B

finifthenelse:... # Resto del programa

Figura 8.5: Traducción de un if/then/else a ensamblador

Tras la evaluación de la condición, el resultado previamente almacenado en%eax se compara, y si es igual a cero se ejecuta elsalto que evita la ejecución del bloque A. En el caso de un if/then/else sin el bloque B, el salto sería a la etiqueta finifthen-else.

En un bloque genérico de este tipo no es preciso asumir que el resultado de la condición está almacenado en%eax. El ejemplo8.1 muestra la traducción de un if/then/else con una condición booleana con múltiples operaciones. Se asume que las variablesx, i y j son de tipo entero y están almacenadas en memoria con etiquetas con el mismo nombre.

Page 146: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

146 / 198

Ejemplo 8.1 Traducción de un if/then/else a ensamblador

Código de alto nivel Código ensamblador

if ((x <= 3) && (i == (j + 1))) {Bloque A

} else {Bloque B

}

cmpl $3, x # Comparar si x <= ←↩3

jg bloqueB # Si falso ir a ←↩bloque B

mov j, %eax # Obtener j + 1inc %eaxcmp %eax, i # Comparar i == (j ←↩

+ 1)jne bloqueB # Si falso ir a ←↩

bloque B... # Traducción del ←↩

bloque A...jmp finifthenelse # Evitar bloque B

bloqueB:... # Traducción del ←↩

bloque B...

finifthenelse: # Final de ←↩traducción

La primer expresión de la conjunción se traduce en una única instrucción cmp. Si esta comparación no es cierta, al tratarse deuna conjunción, se debe ejecutar el bloque B sin necesidad de seguir evaluando. Esto se consigue con el salto jg que contiene lacondición contraria a la del código (x <= 3).

Si la primera parte de la conjunción evalúa a cierto, se pasa a evaluar la segunda. Primero se obtiene el valor de j, se copia en unregistro y se incrementa, pues el código de alto nivel no modifica el valor almacenado en memoria. A continuación se comparacon la variable i y de nuevo, mediante un salto condicional, se ejecuta el bloque pertinente.

8.3.2. Traducción de un switch

A menudo en programación es preciso realizar una operación y ejecutar diferentes bloques de código dependiendo del valorobtenido. La construcción switch mostrada en la figura 8.6 ofrece exactamente esta funcionalidad

switch (expresión) {case valor A:

Bloque Abreak; // Opcional

case valor B:Bloque Bbreak; // Opcional...

default:Bloque por defecto // Opcional

}

Figura 8.6: Estructura de un switch

La semántica de esta construcción establece que primero se evalúa la condición y a continuación se compara el resultado con losvalores de cada bloque precedido por la palabra clave case. Esta comparación se realiza en el mismo orden en el que se definen

Page 147: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

147 / 198

en el código y si alguna de estas comparaciones es cierta, se pasa a ejecutar el código restante en el bloque (incluyendo el restode casos). Si ninguna de las comparaciones es cierta se ejecuta (si está presente) el caso con etiqueta default. La palabra clavebreak se puede utilizar para transferir el control a la instrucción que sigue al bloque switch.

La estructura del código ensamblador para implementar esta construcción debe comenzar por el cálculo del valor de la expresión.A continuación se compara con los valores de los casos siguiendo el orden en el que aparecen en el código. Si una comparacióntiene éxito, se ejecuta el bloque de código que le sigue. Si se encuentra la orden break se debe saltar al final del bloque. Enel caso de que ninguna comparación tenga éxito, se debe pasar a ejecutar el bloque default. Supóngase que la evaluaciónde la expresión es un valor que se almacena en el registro%eax. En la figura 8.7 se muestra la estructura genérica en lenguajeensamblador resultante de traducir un switch en este supuesto.

... # Evaluar la expresión

... # Resultado en %eaxcmp $valorA, %eax # Caso Aje bloqueacmp $valorB, %eax # Caso Bje bloqueb...jmp default

bloquea:... # Traducción del bloque A... #jmp finswitch # Si bloque A tiene break

bloqueb:......jmp finswitch # Si bloque B tiene break......

default:... # Caso por defecto...

finswitch:... # Resto del programa

Figura 8.7: Traducción de un switch a ensamblador

En este esquema se asume que tras obtener el valor de la expresión, éste se mantiene en el registro%eax. La presencia de la líneabreak corresponde directamente con la instrucción jmp finswitch. El ejemplo 8.2 muestra la traducción de un switch. Seasume que las variables son todas de tipo entero y están almacenadas en memoria con etiquetas con el mismo nombre.

Page 148: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

148 / 198

Ejemplo 8.2 Traducción de un switch a ensamblador

Código de alto nivel Código ensamblador

switch (x + i + 3 + j) {case 12:

Bloque Abreak;

case 14:case 16:

Bloque Bcase 18:

Bloque Cbreak;

default:Bloque D

}

mov x, %eax # Evaluar ←↩la expresión

add i, %eaxadd $3, %eaxadd j, %eaxcmp $12, %eax # Caso 12je bloqueacmp $14, %eax # Caso 14je bloquebcmp $16, %eax # Caso 16je bloquebcmp $18, %eax # Caso 18je bloquecjmp default

bloquea:... # ←↩

Traducción del bloque A... #jmp finswitch # Bloque ←↩

A tiene breakbloqueb:

... # ←↩Traducción del bloque B

...bloquec:

... # ←↩Traducción del bloque C

...jmp finswitch # Bloque ←↩

C tiene breakdefault:

... # Bloque ←↩D

...finswitch:

... # Resto ←↩del programa

La condición del ejemplo es una suma de cuatro operandos, con lo que las instrucciones ensamblador correspondientes obtienenlos operandos y acumulan su suma en%eax. A continuación se comparan los sucesivos casos. Si alguna de ellas tiene éxito sepasa a ejecutar el correspondiente bloque de código. Si todas ellas fallan, se ejecuta el salto incondicional al bloque default.En cada uno de los bloques, si está presente la palabra reservada break, ésta se traduce en un salto incondicional al final delbloque.

8.3.3. Traducción de un bucle while

Una de las construcciones más comunes en lenguajes de alto nivel para ejecutar código de forma iterativa es el bucle while. Lafigura 8.8 muestra su estructura. La palabra reservada while da paso a una expresión booleana entre paréntesis que se evalúa yen caso de ser cierta pasa a ejecutar el bloque del código interno tras cuyo final se vuelve de nuevo a evaluar la condición.

Page 149: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

149 / 198

while (expresión booleana) {Código interno

}

Figura 8.8: Estructura de un bucle while

En este bloque es importante tener en cuenta que la expresión booleana se evalúa al menos una vez y se continúa evaluando hastaque sea falsa. Supóngase que la evaluación de la expresión es cero en caso de ser falsa y diferente de cero si es cierta y el valorresultante se almacena en%eax. En la figura 8.9 se muestra la estructura genérica en lenguaje ensamblador resultante de traducirun bucle while en este supuesto.

eval: ... # Evaluar la expresión booleana... # Resultado en %eaxcmp $0, %eaxje finwhile... # Traducción del código interno...jmp eval

finwhile:... # Resto del programa

Figura 8.9: Traducción de un bucle while a ensamblador

Tras evaluar la condición se ejecuta una instrucción que salta al final del bloque si es falsa. En caso de ser cierta se ejecuta elbloque de código y tras él un salto incondicional a la primera instrucción con la que comenzó la evaluación de la condición.El destino de este salto no puede ser la instrucción de comparación porque es muy posible que las variables que intervienen enla condición hayan sido modificadas por lo que la evaluación se debe hacer a partir de estos valores. El ejemplo 8.3 muestrala traducción de un bucle while con una de estas condiciones. Se asume que las variables x, i y j son de tipo entero y estánalmacenadas en memoria con etiquetas con el mismo nombre.

Ejemplo 8.3 Traducción de un bucle while a ensamblador

Código de alto nivel Código ensamblador

while ((x == i) || (y < x)) {Código interno

}

eval: # Comienza ←↩evaluación

mov x, %eaxcmp i, %eax # Comparar si x == ←↩

ije codigointerno # Si cierto ←↩

ejecutar códigocmp y, %eaxjle finwhile # Si falso ir al ←↩

finalcodigointerno:

... # Código interno

...jmp eval # Evaluar de nuevo

finwhile: # Final de ←↩traducción

En este caso la condición del bucle es una disyunción con lo que si una de las condiciones es cierta, se puede ejecutar el código

Page 150: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

150 / 198

interno del bucle sin evaluar la segunda. Por este motivo se utiliza el salto condicional je tras la primera comparación. En casode éxito se pasa a ejecutar directamente el bloque de código interno al bucle. Si la primera condición es falsa se evalúa la segunda.El correspondiente salto condicional en este caso tiene una condición inversa a la incluida en el código, pues si ésta es falsa, sedebe transferir el control al final del bucle.

8.3.4. Traducción de un bucle for

El bucle for, aunque con semántica similar al anterior, tiene una estructura más compleja tal y como se muestra en la figura 8.10.

for (Bloque A; expresión booleana; Bloque B) {Código interno

}

Figura 8.10: Estructura de un bucle for

El bloque A se ejecuta una única vez antes del bucle, a continuación se evalúa la expresión booleana. En caso de ser cierta se pasaa ejecutar el código interno del bucle, y si no, se termina la ejecución del bucle. El bloque B se ejecuta a continuación del códigointerno y justo antes de saltar de nuevo a la evaluación de la expresión booleana. Supóngase que la evaluación de la expresiónbooleana es cero en caso de ser falsa y diferente de cero si es cierta y el valor resultante se almacena en%eax. En la figura 8.11se muestra la estructura genérica en lenguaje ensamblador resultante de traducir un bucle for en este supuesto.

... # Traducción del bloque A

...eval: ... # Evaluar la expresión booleana

... # Resultado en %eaxcmp $0, %eaxje finfor... # Traducción del código interno...... # Traducción del bloque B...jmp eval

finfor:... # Resto del programa

Figura 8.11: Traducción de un bucle for a ensamblador

Las primeras instrucciones corresponden a la traducción del bloque A seguidas de las que evalúan la condición. Se necesitala etiqueta eval como destino del salto incondicional al final del bloque B. A continuación se comprueba el resultado de lacomparación, y si es falso se salta al final del bucle. En caso contrario se ejecuta el código interno que finaliza con las instruccionesdel bloque B y un salto incondicional para que se evalúe de nuevo la condición. El ejemplo 8.4 muestra la traducción de un buclefor con una de estas condiciones. Se asume que las variables i y j son de tipo entero y están almacenadas en memoria conetiquetas con el mismo nombre.

Page 151: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

151 / 198

Ejemplo 8.4 Traducción de un bucle for a ensamblador

Código de alto nivel Código ensamblador

for (i = 0; i <= --j; i++) {Código interno

}

movl $0, i # Bloque Aeval: # Expresión booleana

mov i, %eaxdecl jcmp j, %eax # Comparar si x <= --jjg finfor # Si falso ir al final

codigointerno:... # Código interno...incl i # Bloque Bjmp eval # Evaluar de nuevo

finfor: # Final de traducción

La traducción del bloque A es una única instrucción que almacena un cero en memoria. La expresión booleana incluye eldecremento de la variable j antes de ser utilizada por la comparación. La traducción del bloque B también requiere una únicainstrucción para incrementar el valor de la variable i.

8.4. Ejecución de subrutinas

En la sección anterior se ha mostrado cómo se obtiene una traducción automática de un programa arbitrariamente complejo. Elcompilador primero traduce un bloque a su estructura genérica, luego traduce los bloques internos, y una vez terminado, pasaal bloque siguiente. La estructura global de un programa es una combinación de bloques para los cuales existe una traducciónsistemática. Esta y la codificación de los datos son las dos principales tareas de un compilador para obtener un ejecutable.

El mecanismo que merece un estudio aparte es el de llamada a subrutinas. El desarrollo de programas modulares se basa enla posibilidad de ejecutar un bloque de código múltiples veces con diferentes valores de un conjunto de variables denominadas‘parámetros’ que produce un resultado. Este mecanismo, con diferentes matices, es lo que se denomina como procedimientos,funciones, subprogramas o métodos y están presentes en prácticamente todos los lenguajes de programación de alto nivel.

En el contexto del lenguaje ensamblador se define una subrutina como una porción de código que realiza una operación en basea un conjunto de valores dados como parámetros de forma independiente al resto del programa y que puede ser invocado desdecualquier lugar del código, incluso desde dentro de ella misma.

La ejecución de subrutinas tiene las siguientes ventajas:

Evita código redundante. Durante el diseño de un programa suelen existir ciertos cálculos que deben realizarse en diferenteslugares del código. La alternativa a replicar las instrucciones es encapsularlas en una subrutina e invocar esta cada vez que seanecesario lo cual se traduce en código más compacto.

Facilita la descomposición de tareas. La descomposición de tareas complejas en secuencias de subtareas más simples facilitaenormemente el desarrollo de programas. Esta técnica se suele aplicar de forma sucesiva en lo que se denomina ‘diseñodescendente’ de programas. Cada subtarea se implementa como una rutina.

Facilita el encapsulado de código. El agrupar una operación y sus datos en una subrutina y comunicarse con el resto de unprograma a través de sus parámetros y resultados, hace que si en algún momento se cambia su implementación interna, el restodel programa no requiera cambio alguno.

Además de estas ventajas, el encapsulado de código también facilita la reutilización de su funcionalidad en más de un programamediante el uso de ‘bibliotecas’. Una biblioteca de funciones es un conjunto de subrutinas que realizan cálculos muy comunes

Page 152: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

152 / 198

en la ejecución de programas y que pueden ser utilizados por éstos. Java es un ejemplo de lenguaje que dispone de bibliotecas declases que en su interior ofrecen multitud de métodos.

La desventaja de las subrutinas es que es necesario establecer un protocolo que defina dónde y cómo se realiza esta transferenciade datos para la que se requieren múltiples instrucciones máquina adicionales.

8.4.1. Las instrucciones de llamada y retorno de una subrutina

En ensamblador la llamada a una subrutina se realiza mediante la instrucción CALL cuyo único operando es la dirección de me-moria, generalmente una etiqueta, en la que comienza su código. Tras ejecutar esta instrucción el procesador continua ejecutandola primera instrucción de la subrutina hasta que encuentra la instrucción RET que no tiene operandos y transfiere la ejecución ala instrucción siguiente al CALL que inició el proceso. La figura 8.12 ilustra esta secuencia.

Figura 8.12: Llamada y retorno de una subrutina

La instrucción CALL tiene una funcionalidad similar a un salto incondicional, su único operando denota la siguiente instruccióna ejecutar. La instrucción RET no tiene operandos explícitos pero su efecto, el retorno a la siguiente instrucción tras la llamada,requiere la utilización de operandos implícitos.

Pero la dirección a la que debe retornar el procesador no puede ser un valor fijo para la instrucción RET puesto que dependedel lugar desde donde ha sido invocada la subrutina. Considérese, por ejemplo, una subrutina que se invoca desde dos lugaresdiferentes de un programa. La instrucción RET con la que se termina su ejecución es idéntica en ambos casos pero su direcciónde retorno no. Otra característica de las subrutinas es que su invocación se puede hacer de forma anidada, es decir, que desde unasubrutina se invoca a otra y desde ésta a su vez a otra, hasta una profundidad arbitraria. La figura 8.13 muestra un ejemplo deinvocación anidada de subrutinas y se puede comprobar como la subrutina B es invocada desde diferentes lugares del código.

Page 153: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

153 / 198

Figura 8.13: Invocación anidada de subrutinas

La instrucción RET de la subrutina B retorna la ejecución a la subrutina A en su primera ejecución (denotada por la flechanúmero 3) y al programa principal en su segunda ejecución (denotada por la flecha número 6). Esto hace suponer, por tanto, quela dirección de retorno no puede ser decidida cuando se ejecuta esta instrucción sino en un momento anterior.

El instante en el que se sabe dónde ha de retomarse la ejecución tras una subrutina es precisamente en el momento de suinvocación. Cuando el procesador está ejecutando la instrucción CALL obtiene la dirección de retorno como la de la instrucciónsiguiente en la secuencia.

Por tanto, el procesador, además de modificar la secuencia, al ejecutar la instrucción CALL debe guardar la dirección de retorno enun lugar prefijado del cual será obtenido por la instrucción RET. Pero, durante la ejecución de un programa es preciso almacenarmúltiples direcciones de retorno de forma simultanea.

El que las subrutinas se puedan invocar de forma anidada hace que la utilización de los registros de propósito general paraalmacenar la dirección de retorno no sea factible. La alternativa es almacenarlas en memoria, pero la instrucción RET debe teneracceso a su operando implícito siempre en el mismo lugar. Además, esta zona de memoria debe poder almacenar un númeroarbitrario de direcciones de retorno, pues la invocación de subrutinas se puede anidar hasta niveles arbitrarios de profundidad.

Por tanto, se necesita un área de memoria que pueda almacenar tantas direcciones de retorno como subrutinas están siendoinvocadas de forma anidada en un momento de la ejecución de un programa. La propiedad que tienen estas direcciones es que sealmacenan por la instrucción CALL en un cierto orden, y son utilizadas por la instrucción RET en el orden inverso.

La estructura especialmente concebida para este propósito es la pila. En ella se almacena la dirección de retorno mientras seejecuta el cuerpo de una subrutina. En caso de invocaciones anidadas, las direcciones de retorno pertinentes se guardan en la pilay están disponibles para la instrucción RET en el orden preciso.

La instrucción CALL, por tanto, realiza dos tareas: pasa a ejecutar la instrucción en la dirección dada como operando y almacenaen la cima de la pila la dirección de la instrucción siguiente (al igual que lo haría una instrucción PUSH) que será la instrucciónde retorno. Por su parte, la instrucción RET obtiene el dato de la cima de la pila (igual que lo haría la instrucción POP) y ejecutaun salto incondicional al lugar que indica. Ambas instrucciones, por tanto, modifican el contador de programa.

Del funcionamiento de estas instrucciones se concluye que la cima de la pila justo antes de la ejecución de la primera instrucciónde una subrutina contiene la dirección de retorno, y por tanto, antes de ejecutar la instrucción RET debe apuntar exactamente a lamisma posición. Aunque esta condición es esencial para que el retorno de la subrutina se haga al lugar correcto, los procesadoresno realizan comprobación alguna de que así se produce. Por lo tanto, es responsabilidad del programador en ensamblador elmanipular la pila en una subrutina de forma que la cima de la pila al comienzo de la ejecución sea exactamente la misma quejusto antes de ejecutar la última instrucción.

Durante la ejecución de la subrutina se pueden hacer las operaciones necesarias sobre la pila siempre y cuando se conserve ladirección de retorno. Esta es la explicación de por qué en la sección 6.4 se estipuló la regla de que la pila al comienzo y final deun programa debe ser la misma. El programa en ensamblador que comienza a ejecutar a partir de la etiqueta main también es

Page 154: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

154 / 198

una subrutina que invoca el sistema operativo, y por lo tanto se debe garantizar que la cima es idéntica al comienzo y al final delprograma pues contiene la dirección de retorno.

8.4.2. Paso de parámetros y devolución de resultados

En general una subrutina consiste en una porción de código que realiza una operación con un conjunto de valores proporcionadospor el programa que la invoca denominados parámetros, y que devuelve un resultado. Los parámetros son copias de ciertosvalores que se ponen a disposición de la subrutina y que tras acabar su ejecución se descartan. El resultado, en cambio, es unvalor que la subrutina calcula y copia en un lugar para que el programa invocador lo utilice. La figura 8.14 ilustra la manipulaciónde parámetros y resultado.

Figura 8.14: Parámetros y resultado de una subrutina

Se necesita establecer las reglas que estipulen cómo y dónde deposita el programa que invoca una subrutina estos valores y cómoy dónde se deposita el resultado. En adelante, a la porción de código que realiza la llamada a la subrutina se le denominará‘programa llamador’ mientras que al código de la subrutina se le denominará ‘programa llamado’. Las llamadas a subrutinas sepuede hacer de forma ‘anidada’, es decir, un programa llamado invoca a su vez a otra subrutina con lo que pasa a comportarsecomo programa llamador.

8.4.2.1. Paso de parámetros a través de registro

El paso de parámetros a través de registro consiste en que el programa llamador y el llamado asumen que los parámetros se alma-cenan en ciertos registros específicos. Antes de la instrucción de llamada el programa llamador deposita los valores pertinentesen estos registros y la subrutina comienza a procesarlos directamente.

En general, dada una rutina que recibe n parámetros y devuelve m resultados, se necesita definir en qué registro deposita elprograma llamador la copia de cada uno de los n parámetros, y en qué registro deposita la subrutina la copia del resultadoobtenido. El ejemplo 8.5 muestra las instrucciones necesarias en el caso de una subrutina que recibe como parámetros dosenteros a través de los registros%eax y%ebx y devuelve el resultado a través del registro%ecx.

Page 155: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

155 / 198

Ejemplo 8.5 Paso de parámetros a través de registros

Programa llamador Programa llamado

mov param1, %eaxmov param2, %ebxcall subrutina

mov %ecx, resultado

subrutina:push %... # Salvar registros ←↩

utilizadospush %... # excepto %eax, %ebx y ←↩

%ecx

... # Realizar cálculos

mov ..., %ecx # Poner resultado en % ←↩ecx

pop %... # Restaurar registrospop %...

ret

Al utilizar los registros%eax y%ebx para pasar los parámetros la subrutina no salva su contenido pues dispone de esos valorescomo si fuesen suyos. El registro%ecx, al contener el resultado, tampoco se debe salvar ni restaurar.

El principal inconveniente que tiene este esquema es el número limitado de registros de propósito general. En los lenguajes dealto nivel no hay límite en el número de parámetros que puede tener una función o método en su definición, y por tanto, si estenúmero es muy alto, el procesador puede no tener registros suficientes.

A pesar de esta limitación, en el caso de subrutinas con muy pocos parámetros y que devuelve un único resultado, este mecanismoes muy eficiente pues el procesador no precisa almacenar datos en memoria. Los sistemas operativos suele utilizar esta técnicapara invocaciones de subrutinas internas de estas características.

8.4.2.2. Paso de parámetros a través de memoria

El paso de parámetros a través de memoria consiste en definir una zona de memoria conocida tanto para el programa llamadorcomo para el llamado y en ella se copia el valor de los parámetros y el del resultado para su intercambio. La ventaja de esta técnicaradica en que permite tener un número arbitrario de parámetros, pues tan sólo se requiere una zona más grande de memoria.

En general, para una subrutina que recibe n parámetros y devuelve m resultados se define una zona de memoria cuyo tamaño esla suma de los tamaños de todos ellos así como el orden en el que estarán almacenados. El ejemplo 8.6 muestra la instruccionesnecesarias para el caso de una subrutina que precisa tres parámetros de tamaño 32 bits y devuelve dos resultados de tamaño 8bits. Se asume que la zona de memoria está definida a partir de la etiqueta params.

Page 156: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

156 / 198

Ejemplo 8.6 Paso de parámetros a través de memoria

Programa llamador Programa llamado

mov params, %eaxmov v1, %ebxmov %ebx, (%eax)mov v2, %ebxmov %ebx, 4(%eax)mov v3, %ebxmov %ebx, 8(%eax)call subrutinamov 12(%eax), %ah

mov 13(%eax), %ah

subrutina:push %... # Salvar registros ←↩

utilizadospush %...

mov params, %ebx # Acceso a los ←↩parámetros

mov (%ebx), ...mov 4(%ebx), ...mov 8(%ebx), ...... # Realizar cálculos

mov %dh, 12(%ebx) # Poner resultadomov %dl, 13(%ebx)

pop %... # Restaurar ←↩registros

pop %...

ret

El principal inconveniente de esta técnica es que necesita tener estas zonas de memoria previamente definidas. Además, en elcaso de invocación anidada de subrutinas, se necesitan múltiples espacios de parámetros y resultados pues mientras la ejecuciónde una subrutina no termina, éstos siguen teniendo validez.

El incluir esta definición junto con el código de una subrutina parecería una solución idónea, pues al escribir sus instrucciones sesabe el número y tamaño de parámetros y resultados. Pero existen subrutinas denominadas ‘recursivas’ que se caracterizan porcontener una invocación a ellas mismas con un conjunto de parámetros diferente.

La conclusión es que se precisan tantas zonas para almacenar parámetros y devolver resultados como invocaciones pendientes determinar en cada momento de la ejecución. Pero este requisito de vigencia es idéntico al que tiene la dirección de retorno de unasubrutina. Es más, la dirección de retorno se puede considerar un valor más que el programa llamador pasa al llamado para queéste lo utilice. En esta observación se basa la siguiente técnica de paso de parámetros.

8.4.2.3. Paso de parámetros a través de la pila

El paso de parámetros a través de la pila tiene múltiples ventajas. En primer lugar, tanto parámetros como resultados se puedenconsiderar resultados temporales que tienen validez en un período muy concreto de la ejecución de un programa por lo que lapila favorece su manipulación. Además, dada una secuencia de llamadas a subrutinas, el orden de creación y destrucción de estosparámetros es el inverso tal y como permiten las instrucciones de gestión de la pila.

En general, para una subrutina que recibe n parámetro y devuelve m resultados el programa llamador reserva espacio en la cimade la pila para almacenar estos datos justo antes de ejecutar la instrucción CALL y lo elimina justo a continuación.

Pero en la subrutina es necesario un mecanismo eficiente para acceder a la zona de parámetros y resultados. Al estar ubicada enla pila lo más intuitivo es utilizar el registro%esp que apunta a la cima y el modo de direccionamiento base + desplazamientomediante la utilización de los desplazamientos pertinentes. Pero el inconveniente de este método es que la cima de la pila puedefluctuar a lo largo de la ejecución de la subrutina y por tanto los desplazamientos a utilizar varían.

Para que el acceso a los parámetros no dependa de la posición de la cima de la pila y se realice con desplazamientos constantes alo largo de la ejecución de la subrutina, las primeras instrucciones almacenan una copia del puntero de pila en otro registro (ge-neralmente%ebp) y al fijar su valor, los accesos a la zona de parámetros y resultados se realizan con desplazamientos constantes.Pero para preservar el valor de los registros, antes de crear este duplicado es preciso guardar en la pila una copia de este registro.

Page 157: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

157 / 198

El ejemplo 8.7 muestra las instrucciones necesarias para el caso de una subrutina que precisa tres parámetros de tamaño 32 bitsy devuelve un resultado de 8 bits.

Ejemplo 8.7 Paso de parámetros a través de la pila

Programa llamador Programa llamado

sub $4, %esppush v3push v2push v1call subrutinaadd $12, %esp

pop resultado

subrutina:push %ebp # Guardar registro ←↩

%ebpmov %esp, %ebp # Apuntar a punto ←↩

fijo en pilapush %... # Salvar registros ←↩

utilizadospush %...

mov 8(%ebp), ... # Acceso a los ←↩parámetros

mov 12(%ebp), ...mov 16(%ebp), ...... # Realizar cálculos

mov ..., 20(%ebx) # Poner resultado

pop %... # Restaurar ←↩registros

pop %...mov %ebp, %esp # Restaurar %esp y ←↩

%ebppop %ebp

ret

La primera instrucción del programa llamador modifica el puntero de la pila para reservar espacio donde almacenar el resultado.Al ser una posición de memoria sobre la que se escribirá el resultado no es preciso escribir ningún valor inicial, de ahí que no seutilice la instrucción push.

A continuación se depositan en la pila los valores de los parámetros. El orden en que se almacenan debe ser conocido por elprograma llamador y el llamado. Tras la ejecución de la subrutina se eliminan de la pila los parámetros, que al desempeñarningún papel, basta con corregir el valor de la cima dejando la pila preparada para obtener el valor del resultado.

Por su parte, el programa llamado guarda la copia del registro%ebp para justo a continuación copiar el valor de%esp y portanto fija su valor a la cima de la pila. A partir de este instante, cualquier dato que se ponga en la pila no afecta el valor de%-ebp y el desplazamiento para acceder a los parámetros es respectivamente de 8, 12 y 16 pues en la posición debajo de la cimase encuentra la dirección de retorno. Para depositar el resultado se utiliza el desplazamiento 20. Tras terminar el cálculo delresultado se procede a deshacer la estructura de datos creada en la pila en orden inverso. Primero se descargan de la pila losregistros salvados y a continuación se restaura el valor del registro%ebp dejando en la cima la dirección de retorno que necesitala instrucción ret.

A la porción de memoria en la pila que contiene el espacio para la devolución de resultados, los parámetros, la dirección deretorno, la copia de%ebp se le denomina el ‘bloque de activación’. Al registro%ebp que ofrece un punto fijo de referencia a losdatos se le denomina el ‘puntero’ al bloque de activación.

8.4.2.4. Almacenamiento de variables locales a una subrutina

Además de la capacidad de definir y ejecutar subrutinas, los lenguajes de programación de alto nivel permiten la definición devariables locales. El ámbito de validez se reduce al instante en que se está ejecutando el código de la subrutina. De nuevo se

Page 158: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

158 / 198

precisa un mecanismo que gestione de forma eficiente estas variables. El ejemplo 8.8 muestra la definición de un método en Javaen el que las variables i, str y p son de ámbito local.

Ejemplo 8.8 Definición de variables locales a un método

int traducir(Representante r, int radix) {int i; // Variables localesString str;Punto p;

i = 0;str = new String(...);punto = ......return i;

}

El ámbito de estas variables no impide que el valor de alguna de ellas sea devuelto como resultado tal y como muestra el métododel ejemplo. La última línea copia el valor de la variable local en el lugar en el que se devuelve el resultado, y por tanto estádisponible para el programa llamador.

El ámbito de estas variables es idéntico al de los parámetros y al de la dirección de retorno, por lo que para almacenar estasvariables se pueden utilizar cualquiera de las tres técnicas descritas anteriormente: en registros, en posiciones arbitrarias dememoria y en la pila.

El almacenamiento en la pila se hace en el bloque de activación justo a continuación de haber establecido el registro%ebpcomo puntero al bloque de activación. De esta forma, como el número de variables locales es siempre el mismo, utilizandodesplazamientos con valores negativos y el registro base%ebp se accede a ellas desde cualquier punto de la subrutina.

8.5. Gestión del bloque de activación

De las técnicas descritas para la invocación de subrutinas, la que crea el bloque de activación en la pila es la más utilizada por loslenguajes de alto nivel. En la Tabla 8.1 se muestran los pasos a seguir por el programa llamador y el llamado para crear y destruirel bloque de activación.

Tras restaurar el valor de los registros utilizados por la subrutina, el estado de la pila es tal que en la cima se encuentra elespacio para las variables locales y a continuación la copia del valor anterior de%ebp. Como el propio%ebp apunta a esa mismaposición, la forma más fácil de restaurar la cima de la pila al valor correcto es asignándole a%esp el valor de%ebp. De estaforma no es preciso tener en cuenta el tamaño de la zona reservada para las variables locales. Esta técnica funciona incluso en elcaso de que una subrutina no tenga variables locales.

8.6. Ejemplo de evolución del bloque de activación

Considérese un programa que invoca a la subrutina cuenta que dada la dirección de un string terminado en cero y un carácter,devuelve el número de veces que el carácter aparece en el string como entero. La pila que recibe la subrutina tiene, en ordencreciente de desplazamiento desde el puntero al bloque de activación, la dirección de retorno (siempre está presente como primervalor), la dirección del string, el carácter a comprobar como byte menos significativo del operando en la pila y el espacio para elresultado. El fragmento de código para invocar a esta subrutina se muestra en el ejemplo 8.9. Se asume que la letra a buscar estáalmacenada en la etiqueta letra y el string en la etiqueta mensaje.

Page 159: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

159 / 198

Programa llamador Programa llamado

1. Reserva espacio en la pila para almacenar losresultados.

2. Carga los parámetros en orden en la pila.

3. Ejecuta la instrucción de llamada a subrutina.

4. Descarga los parámetros de la pila.

5. Obtiene el resultado de la pila.

1. Salva el valor de%ebp para utilizar como puntero albloque de activación.

2. Copia el valor de%esp en%ebp.

3. Reserva espacio en la pila para variables locales.

4. Salva los registros que se utilizan en la subrutina.

5. Ejecuta el código de la subrutina.

6. Deposita el resultado en el espacio reservado a talefecto.

7. Restaura el valor de los registros salvados.

8. Iguala la cima de la pila al puntero al bloque deactivación.

9. Restaura el valor del registro%ebp.

10. Ejecuta la instrucción de retorno de subrutina.

Tabla 8.1: Pasos para la gestión del bloque de activación

Ejemplo 8.9 Invocación de la rutina cuenta

...sub $4, %esp # Espacio para el resultadopush letra # Parámetros en el orden correctopush mensajecall cuenta # Invocación de la subrutinaadd $8, %esp # Descarga del espacio para parámetrospop %eax # Resultado en %eax...

La instrucción push letra tiene por operando una etiqueta que apunta a un dato de tamaño byte. Como los operandos dela pila son de 4 bytes, en ella se depositan la letra y los tres siguientes bytes. Esto no tiene importancia porque la subrutinaúnicamente accede al byte de menos peso tal y como se ha especificado en su definición. La figura 8.15 muestra la evolución dela pila desde el punto de vista del programa llamador.

Page 160: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

160 / 198

Figura 8.15: Evolución de la pila desde el punto de vista del programa llamador

El código de la subrutina cuenta se muestra en el ejemplo 8.10.

Page 161: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

161 / 198

Ejemplo 8.10 Código de la rutina cuenta

cuenta: push %ebp # Salvar %ebpmov %esp, %ebp # Crear puntero a bloque de activación

sub $4, %esp # Espacio para variable local: contador

push %eax # Salvar registros utilizadospush %ebxpush %ecx

movl $0, -4(%ebp) # Contador = 0mov 8(%ebp), %eax # Dirección base del stringmov 12(%ebp), %cl # Letra a comparar en %clmov $0, %ebx # Registro índice

bucle: cmpb $0, (%eax, %ebx) # Detectar final de stringje res

cmpb %cl, (%eax, %ebx) # Compara letra dada con letra en stringjne incr # Si iguales incrementar contadorincl -4(%ebp)

incr: inc %ebx # Incrementar registro índicejmp bucle

res: mov -4(%ebp), %eax # Mover contador a resultadomov %eax, 16(%ebp)

pop %ecx # Restaurar registrospop %ebxpop %eax

mov %ebp, %esp # Eliminar variables localespop %ebp # Restaurar %ebpret

La subrutina almacena el número de veces que aparece la letra en el string dado como una variable local en la pila. Tras finalizarel bucle, su valor se transfiere al lugar en el que lo espera el programa llamador. La figura 8.16 muestra la evolución de la piladurante la ejecución de la subrutina.

Page 162: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

162 / 198

Figura 8.16: Evolución de la pila durante la llamada a cuenta

8.7. Ejercicios

1. Partiendo del código del ejemplo 8.1, traducir la nueva versión que se muestra en la siguiente figura con la modificaciónen la última parte de la condición:

Código de alto nivel

if ((x <= 3) && (i == j++)) {Bloque A

} else {Bloque B

}

¿En qué lugar se debe insertar la instrucción que incrementa la variable j para mantener el significado de esta construc-ción?

Si la primera sub-expresión de la conjunción es falsa, ¿se incrementa la variable j?

2. Traducir el siguiente bucle en lenguaje de alto nivel a la porción de código equivalente en lenguaje ensamblador de laarquitectura IA-32. Se asume que todas las variables son de tipo entero.

Page 163: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

163 / 198

for (i = a + b; ((c + d) >= 10) && (i <= (d + e)); i = i + f - g - h ) {g--;f++;a = b + 10;

}

Las variables han sido definidas de la siguiente forma:

a: .int 10b: .int 20c: .int 30d: .int 40e: .int 50f: .int 60g: .int 70h: .int 80i: .int 10

La solución puede utilizar cualquier modo de direccionamiento excepto el modo absoluto. Al tratarse de una porción decódigo aislada, no es preciso salvar ni restaurar el contenido de los registros. La solución debe ser lo más corta posible yutilizar el menor número de registros de propósito general.

3. La mayor parte de los lenguajes de alto nivel que ofrecen bucles de tipo while también ofrecen otro bucle de estructurasimilar denominado do/while. La diferencia es que el bloque comienza por la palabra clave do seguida de un bloque decódigo entre llaves y termina con la palabra while seguida de una condición booleana entre paréntesis.

El bloque de código se ejecuta al menos una vez y tras él se evalúa la condición para determinar si se continúa iterando.Escribir la estructura en codigo ensamblador resultante de traducir esta construcción. Se puede asumir que el resultado deevaluar la condición está almacenado en%eax.

4. Escribir las reglas para el paso de parámetros y devolución de resultado a través de la pila:

Por parte del programa que llama a la subrutina:

Por parte de la subrutina:

5. Un programador ha escrito la siguiente rutina:

rutina:push %ebpmov %esp, %ebpadd $13, 4(%ebp)pop %ebpret

El programa principal que invoca a esta rutina contiene las siguientes instrucciones tal y como las muestra el compiladoren su informe sobre el restulado del ensamblaje:

1 .data2 0000 50726F67 msg: .asciz "Programa terminado.\n"2 72616D612 207465722 6D696E612 646F2E0A34 .text5 .globl main6 main:7 0000 50 push %eax8 0001 51 push %ecx9 0002 52 push %edx

10

Page 164: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

164 / 198

11 0003 E8FCFFFF call rutina # Llamada a rutina dada11 FF1213 0008 68000000 push $msg13 0014 000d E8FCFFFF call printf14 FF15 0012 83C404 add $4, %esp1617 0015 5A pop %edx18 0016 59 pop %ecx19 0017 58 pop %eax20 0018 C3 ret

Explicar detalladamente cuál es el resultado de la ejecución de este programa. ¿Ejecuta correctamente? ¿Qué escribe porpantalla? ¿Por qué?

6. El paso de resultados y devolución de resultados se puede hacer a través de registros, memoria o la pila, pero nada impideutilizar una técnica diferente para parámetros y resultados. Describir las reglas de creación del bloque de activación paralos siguientes supuestos.

a. Parámetros en la pila y resultados a través de registros.

b. Parámetros en registro y resultados a través de la pila.

Page 165: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

165 / 198

Apéndice A

Subconjunto de instrucciones de la arquitecturaIA-32

La arquitectura IA-32 dispone de un lenguaje máquina con cientos de instrucciones para múltiples tipos de tareas diferentes. Eneste apéndice se describen en detalla tan sólo un subconjunto mínimo que permite realizar operaciones sencillas sobre tipos dedatos tales como strings y enteros.

A.1. Nomenclatura

Para la descripción detallada del subconjunto de instrucciones de esta arquitectura se utiliza la siguiente nomenclatura:

%reg: Denota cualquiera de los ocho registros de propósito general.

inm: Denota una constante numérica. En ensamblador, el valor numérico debe ir precedido por el símbolo $. También seincluyen en esta categoría las expresiones $etiq, donde etiq corresponde con el nombre de una de las etiquetas definidasen el código.

mem: Denota el nombre de una etiqueta definida en el código. Nótese que en este caso no se utiliza el prefijo $ pues si fueseasí se trataría de una constante.

INSs: Cuando el código de operación de una instrucción termina en s esto denota que la instrucción requiere un sufijo detamaño B, W o L.

A.2. Instrucciones de movimiento de datos

A.2.1. MOV: Movimiento de datos

Instrucción Descripción

MOV %regA, %regB Mueve el contenido de%regA al registro%regB.

MOV $inm, %reg Mueve inm al registro%reg.

MOV mem, %regMueve el contenido almacenado en la posición mem alregistro%reg.

Page 166: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

166 / 198

Instrucción Descripción

MOV %reg, mem Mueve el contenido de%reg a la posición mem.

MOVs $inm, mem

Mueve inm, codificado con los bits especificados por elsufijo s al dato cuyo tamaño está especificado por el sufijos y que está almacenado a partir de la posición mem.

La instrucción de mover recibe dos operandos y mueve el primero al lugar donde indica el segundo. Esta instrucción no modificaninguno de los flags de la palabra de estado.

A.2.2. PUSH: Instrucción de carga sobre la pila

Instrucción Descripción

PUSH %regAlmacena el contenido de%reg en la posición anterior a laque apunta el puntero de pila.

PUSH mem

Almacena el dato de 32 bits que está almacenado a partirde la posición mem en la posición anterior a la que apuntael puntero de pila.

PUSH $inmAlmacena inm codificado con 32 bits en la posiciónanterior a la que apunta el puntero de pila.

Esta instrucción recibe un único operando y manipula siempre operandos de 32 bits, por lo tanto no es preciso utilizar ningúnsufijo de tamaño. El procesador toma el valor del registro puntero de pila, le resta 4 y almacena el operando dado en los cuatrobytes de memoria a partir de la posición del puntero de pila. Esta instrucción no modifica ninguno de los flags de la palabra deestado.

A.2.3. POP: Instrucción de descarga de la pila

Instrucción Descripción

POP %reg

Almacena el contenido al que apunta el puntero de pilaen%reg. Modifica el puntero a la cima para que apunte ala siguiente posición de la pila.

POP mem

Almacena los 32 bits a los que apunta el puntero de pila apartir de la posición mem. Modifica el puntero a la cimapara que apunte a la siguiente posición de la pila.

Esta instrucción recibe un único operando y manipula siempre operandos de 32 bits, por lo tanto no es preciso utilizar ningúnsufijo de tamaño. El procesador toma el valor del registro puntero de pila y mueve ese dato al lugar que le indique el operandode la instrucción. Tras esta transferencia, se suma el valor 4 al registro puntero de pila. Esta instrucción no modifica ninguno delos flags de la palabra de estado.

A.2.4. XCHG: Instrucción de intercabmio

Page 167: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

167 / 198

Instrucción Descripción

XCHG %regA, %regB

XCHG %reg, mem

XCHG mem, %reg

Intercambia los valores de sus dos operandos. Cuando unoperando está en memoria, se intercambia el datoalmacenado a partir de la posición de memoria dada. Almenos uno de los operandos debe ser de tipo registro.

Esta instrucción utiliza un registro temporal interno del procesador para intercambiar los operandos. No se modifica ninguno delos flags de la palabra de estado.

A.3. Instrucciones aritméticas

A.3.1. ADD: Instrucción de suma

Instrucción Descripción

ADD %regA, %regB Suma el contenido de%regA al contenido de%regB.

ADD $inm, %reg Suma inm al contenido de%reg.

ADD mem, %regSuma el contenido almacenado en la posición mem alcontenido de%reg.

ADD %reg, memSuma el contenido de%reg al contenido almacenado en laposición mem.

ADDs $inm, mem

Suma inm, codificado con los bits especificados por elsufijo s al dato cuyo tamaño está especificado por el sufijos y que está almacenado a partir de la posición mem.

La instrucción de suma recibe dos operandos, los suma y deposita el resultado en el lugar especificado por el segundo operando.Se pierde, por tanto, el valor del segundo operando. Los flags de la palabra de estado OF, SF, ZF, PF y CF se modifican deacuerdo al resultado obtenido.

A.3.2. SUB: Instrucción de resta

Instrucción Descripción

SUB %regA, %regB Resta el contenido de%regA del contenido de%regB.

SUB $inm, %reg Resta inm del contenido de%reg.

Page 168: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

168 / 198

Instrucción Descripción

SUB mem, %regResta el contenido almacenado en la posición mem delcontenido de%reg.

SUB %reg, memResta el contenido de%reg del contenido almacenado enla posición mem.

SUBs $inm, mem

Resta inm, codificado con los bits especificados por elsufijo s del dato cuyo tamaño está especificado por elsufijo s y que está almacenado a partir de la posición mem.

La instrucción de resta recibe dos operandos op1 y op2, realiza la operación op2 - op1 y almacena el resultado en el lugarespecificado por el segundo operando. Se pierde, por tanto, el valor del segundo operando. Los flags de la palabra de estado OF,SF, ZF, PF y CF se modifican de acuerdo al resultado obtenido.

A.3.3. INC: Instrucción de incremento

Instrucción Descripción

INC %reg Suma uno al contenido de%reg.

INCs mem

Suma uno, codificado con los bits especificados por elsufijo s al dato cuyo tamaño está especificado por el sufijos y que está almacenado a partir de la posición mem.

La instrucción de incremento recibe un único operando al que le suma el valor 1. Esta instrucción tiene la particularidad de queno modifica el flag de acarreo (CF). Los flags de la palabra de estado OF, SF, PF y ZF sí se modifican de acuerdo al resultadoobtenido.

A.3.4. DEC: Instrucción de decremento

Instrucción Descripción

DEC %reg Resta uno del contenido de%reg.

DECs mem

Resta uno, codificado con los bits especificados por elsufijo s del dato cuyo tamaño está especificado por elsufijo s y que está almacenado a partir de la posición mem.

La instrucción de decremento recibe un único operando al que le resta el valor 1. Esta instrucción tiene la particularidad de queno modifica el flag de acarreo (CF). Los flags de la palabra de estado OF, SF, PF y ZF sí se modifican de acuerdo al resultadoobtenido.

A.3.5. NEG: Instrucción de cambio de signo

Page 169: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

169 / 198

Instrucción Descripción

NEG %regToma el contenido de%reg, cambia su signo y sealmacena en%reg.

NEGs mem

Toma el número codificado con los bits especificados por elsufijo s y almacenado a partir de la posición mem y lecambia el signo.

La instrucción de decremento recibe un único operando y la operación que realiza es equivalente a multiplicar por -1. El operandose asume que está codificado en complemento a 2. Esta instrucción tiene la particularidad de que asigna directamente el valor 1al flag de acarreo (CF) excepto si el operando tiene el valor 0. Los flags de la palabra de estado OF, SF, PF y ZF sí se modificande acuerdo al resultado obtenido.

A.3.6. MUL: Instrucción de multiplicación sin signo

Instrucción Descripción

MUL %reg

Multiplica el contenido de%reg por el registro%al,%axo%eax dependiendo de si el tamaño del operando es de 8,16 o 32 bits respectivamente. El resultado se almacenaen%ax, el registro de 32 bits resultante deconcatenar%dx:%ax (%dx el más significativo) o elregistro de 64 bits resultante de concatenar%edx:%eax(%edx el más significativo) dependiendo de si el operandodado es de 8, 16 o 32 bits respectivamente.

MULs mem

Multiplica el dato codificado con los bits especificado porel sufijo s y almacenado a partir de la posición mem por elregistro%al,%ax o%eax dependiendo de si el tamaño deloperando es de 8, 16 o 32 bits respectivamente. El resultadose almacena en%ax, el registro de 32 bits resultante deconcatenar%dx:%ax (%dx el más significativo) o elregistro de 64 bits resultante de concatenar%edx:%eax(%edx el más significativo) dependiendo de si el sufijoespecifica 8, 16 o 32 bits respectivamente.

Esta instrucción utiliza dos operandos, pero uno de ellos es implícito, es decir, no aparece en la instrucción. Este multiplicandose obtiene de%al,%ax o%eax dependiendo de si la operación debe utilizar datos de 8, 16 o 32 bits.

Se permite, por tanto, la utilización de 3 posibles tamaños de operandos: 8, 16 y 32 bits. Ambos operandos tienen idénticotamaño. El problema de la multiplicación es que si en general se multiplican dos números de tamaño n y m bits, se precisann + m bits para representar el restulado. Como consecuencia de esto, el resultado de esta instrucción se almacena en%ax si lamultiplicación es de dos números de 8 bits, en el registro de 32 bits resultante de concatenar%dx:%ax, con%dx como partemás significativa, si se multiplican dos números de 16 bits, y en caso de multiplicación de dos números de 32 bits, se almacenaen la concatenación%edx:%ecx como un registro de 64 bits con%edx como parte más significativa.

La razón por la que no se utiliza uno de los registros de 32 bits para almacenar el producto de dos operandos de 16 bits eshistórica. Han existido procesadores anteriores a este en el que sólo había registros de 16 bits. Para almacenar un operando de32 bits había que realizar esta concatenación. Los nuevos procesadores disponen de registros de 32 bits, pero por mantener ellenguaje máquina compatible con las versiones anteriores, esta instrucción conserva la descripción anterior. La Tabla A.1 muestrala relación entre el tamaño de los operandos y el lugar en el que se almacena el resultado.

Los únicos flags que se modifican con esta instrucción son CF y OF. Ambos bits se ponen a 1 cuando la mitad más significativadel resultado tiene alguno de sus bits a 1. El resto de flags tienen valores no definidos tras ejecutar esta instrucción.

Page 170: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

170 / 198

Tamaño de Operando Operando Implícito Operando Explícito ResultadoByte %al %reg ó mem %ax

Word (2 bytes) %ax %reg ó mem %dx:%axDoubleword (4 bytes) %eax %reg ó mem %edx:%eax

Tabla A.1: Opciones de la multiplicación sin signo

A.3.7. DIV: Instrucción de división sin signo

Instrucción Descripción

DIV %reg

Esta instrucción tiene tres versiones posibles. Divide elregistro%ax, los 32 bits obtenidos al concatenar losregistros%dx:%ax o los 64 bits obtenidos al concatenarlos registros%edx:%eax entre%reg. Como resultado sedeposita el cociente en%al,%ax o%eax y el restoen%ah,%dx o%edx respectivamente. Se consideran todoslos operandos como números naturales.

DIVs mem

Esta instrucción tiene tres versiones posibles. Divide elregistro%ax, los 32 bits obtenidos al concatenar losregistros%dx:%ax o los 64 bits obtenidos al concatenarlos registros%edx:%eax entre el dato codificado según elsufijo s y almacenado a partir de la posición de memoriamem. Como resultado se deposita el cociente en%al,%axo%eax y el resto en%ah,%dx o%edx respectivamente.

Esta instrucción utiliza dos operandos: dividendo y divisor. Tan sólo se especifica en la instrucción el divisor. El dividendo esimplícito y tiene tamaño doble al del divisor y se obtiene de%ax (16 bits), la concatenación de los registros%dx:%ax (32 bits)o la concatenación de los registros%edx:%eax (64 bits) dependiendo de si el divisor es de 8, 16 o 32 bits respectivamente.

La instrucción devuelve dos resultados: cociente y resto. El cociente se devuelve en%al,%ax o%eax y el resto en%ah,%dxo%edx. La Tabla A.2 muestra la relación entre el tamaño de los operandos y el lugar en el que se almacena el resultado.

Tamaño deOperandos Dividendo Divisor Cociente Resto Valor Máximo

Cociente

Word/Byte %ax1 byte%reg ó

mem%al %ah 255

Doubleword/Word %dx:%ax2 bytes%reg ó

mem%ax %dx 65.535

Quadword/Doubleword%edx:%eax 4 bytes%reg ómem

%eax %edx 232 - 1

Tabla A.2: Opciones de la división sin signo

Ninguno de los flags de la palabra de estado tiene valor definido tras ejecutar esta instrucción.

A.3.8. IMUL: Instrucción de multiplicación con signo

La instrucción para multiplicar dos enteros con signo tiene tres posibles formatos dependiendo del número de operandos explíci-tos.

El formato con un único operando se interpreta de forma idéntica a la instrucción de multiplicación sin signo MUL (ver secciónA.3.6). El segundo operando es implícito y tiene idéntico tamaño al explícito. El resultado tiene tamaño doble que los operandos.

Instrucción Descripción

IMUL %reg

Multiplica el contenido de%reg por el registro%al,%axo%eax dependiendo de si el tamaño del operando es de 8,16 o 32 bits respectivamente. El resultado se almacenaen%ax, el registro de 32 bits resultante deconcatenar%dx:%ax (%dx el más significativo) o elregistro de 64 bits resultante de concatenar%edx:%eax(%edx el más significativo) dependiendo de si el operandodado es de 8, 16 o 32 bits respectivamente.

Page 171: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

171 / 198

Instrucción Descripción

IMULs mem

Multiplica el dato codificado con los bits especificado porel sufijo s y almacenado a partir de la posición mem por elregistro%al,%ax o%eax dependiendo de si el tamaño deloperando es de 8, 16 o 32 bits respectivamente. El resultadose almacena en%ax, el registro de 32 bits resultante deconcatenar%dx:%ax (%dx el más significativo) o elregistro de 64 bits resultante de concatenar%edx:%eax(%edx el más significativo) dependiendo de si el sufijoespecifica 8, 16 o 32 bits respectivamente.

La segunda versión de esta instrucción contiene dos operandos. El segundo de ellos es a la vez multiplicando y destino delresultado y debe ser uno de los registro de propósito general. En esta versión, tanto operandos como resultado tienen idénticotamaño, con lo que hay una mayor probabilidad de overflow.

Instrucción Descripción

MUL %regA, %regB

Multiplica el contenido de%regA por el contenidode%regB. Los registros deben tener idéntico tamaño ysólo pueden ser de 16 o 32 bits, no de 8.

MUL $inm, %regMultiplica inm por el contenido de%reg. El registro sólopuede ser de 16 o 32 bits.

MUL mem, %reg

Multiplica el contenido almacenado a partir de la posiciónmem por el contenido de%reg. El registro sólo puede serde 16 o 32 bits.

La tercera versión de la instrucción de multiplicación consta de tres operandos. El primero es un multiplicando y debe ser unaconstante, el segundo es también un multiplicando y debe ser una posición de memoria o un registro. El tercer operando es dondese guarda el resultado y debe ser un registro de propósito general.

Instrucción Descripción

MUL $inm, %regA, %regB

Multiplica $inm por el contenido de%regA y almacena elrestulado en%regB. Los registros deben tener idénticotamaño y sólo pueden ser de 16 o 32 bits, no de 8.

MUL $inm, mem, %reg

Multiplica $inm por el dato almacenado a partir de laposición mem y almacena el resultado en%reg. El registrosólo puede ser de 16 o 32 bits.

De las tres versiones posibles para esta operación, sólo la primera deposita el resultado del tamaño apropiado para evitar desbor-damientos. El formato con dos y tres operandos realiza la multiplicación, obtiene todos los bits del resultado y posteriormentelos trunca para almacenar en destino. Los únicos flags que se modifican con esta instrucción son CF y OF. Ambos bits se ponena 1 cuando la mitad más significativa del resultado tiene alguno de sus bits a 1. Nótese que estos dos flags son los que indican, enel caso de la instrucción con dos y tres operandos, si el resultado obtenido ha sido truncado para almacenarse en destino. El restode flags tienen valores no definidos tras ejecutar esta instrucción.

A.3.9. IDIV: Instrucción de división con signo

El comportamiento de esta instrucción es idéntico al de la instrucción DIV (ver sección A.3.7) con la diferencia de que losoperandos son números enteros.

Page 172: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

172 / 198

Instrucción Descripción

IDIV %reg

Esta instrucción tiene tres versiones posibles. Divide elregistro%ax, los 32 bits obtenidos al concatenar losregistros%dx:%ax o los 64 bits obtenidos al concatenarlos registros%edx:%eax entre%reg. Como resultado sedeposita el cociente en%al,%ax o%eax y el restoen%ah,%dx o%edx respectivamente. Los operandos setratan como números enteros.

IDIVs mem

Esta instrucción tiene tres versiones posibles. Divide elregistro%ax, los 32 bits obtenidos al concatenar losregistros%dx:%ax o los 64 bits obtenidos al concatenarlos registros%edx:%eax entre el dato codificado según elsufijo s y almacenado a partir de la posición de memoriamem. Como resultado se deposita el cociente en%al,%axo%eax y el resto en%ah,%dx o%edx respectivamente.Los operandos se tratan como números enteros.

Al igual que la instrucción DIV, esta instrucción utiliza dos operandos: dividendo y divisor. Tan sólo se especifica en la instrucciónel divisor. El dividendo es implícito y tiene tamaño doble al del divisor y se obtiene de%ax (16 bits), la concatenación de losregistros%dx:%ax (32 bits) o la concatenación de los registros%edx:%eax (64 bits) dependiendo de si el divisor es de 8, 16o 32 bits respectivamente.

La instrucción devuelve dos resultados: cociente y resto. El cociente se devuelve en%al,%ax o%eax y el resto en%ah,%dxo%edx. La Tabla A.2 muestra la relación entre el tamaño de los operandos y el lugar en el que se almacena el resultado.

Tamaño deOperandos Dividendo Divisor Cociente Resto Rango del

Cociente

Word/Byte %ax1 byte%reg ó

mem%al %ah -128 a 127

Doubleword/Word %dx:%ax2 bytes%reg ó

mem%ax %dx -32.768 a 32.767

Quadword/Doubleword%edx:%eax 4 bytes%reg ómem

%eax %edx -231 - 1 a 231

Tabla A.3: Opciones de la división con signo

Ninguno de los flags en la palabra de estado tiene valores definidos tras ejecutar esta instrucción.

A.4. Instrucciones lógicas

A.4.1. AND: Instrucción de conjunción

Instrucción Descripción

AND %regA, %regBRealiza la conjunción bit a bit del contenido de%regA conel contenido de%regB. Deposita el resultado en%regB.

AND $inm, %regRealiza la conjunción bit a bit entre inm y el contenidode%reg. Deposita el resultado en%reg.

AND mem, %reg

Realiza la conjunción bit a bit entre el contenidoalmacenado en la posición mem y el contenido de%reg.Deposita el resultado en%reg.

Page 173: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

173 / 198

Instrucción Descripción

AND %reg, mem

Realiza la conjunción bit a bit entre el contenido de%reg yel contenido almacenado a partir de la posición mem. Elresultado se almacena en memoria a partir de la posiciónmem.

ANDs $inm, mem

Realiza la conjunción bit a bit entre inm, codificado conlos bits especificados por el sufijo s con el dato cuyotamaño está especificado por el sufijo s y que estáalmacenado a partir de la posición mem. El resultado sealmacena en memoria a partir de la posición mem.

La conjunción bit a bit significa que ambos operandos deben tener el mismo tamaño y que cada bit del resultado se calculahaciendo la conjunción de los correspondientes bits de ambos operandos. Los flags OF y CF se ponen a cero. Los flags SF, ZF yPF se modifican de acuerdo con el resultado.

A.4.2. OR: Instrucción de disyunción

Instrucción Descripción

OR %regA, %regBRealiza la disyunción bit a bit del contenido de%regA conel contenido de%regB. Deposita el resultado en%regB.

OR $inm, %regRealiza la disyunción bit a bit entre inm y el contenidode%reg. Deposita el resultado en%reg.

OR mem, %reg

Realiza la disyunción bit a bit entre el contenidoalmacenado en la posición mem y el contenido de%reg.Deposita el resultado en%reg.

OR %reg, mem

Realiza la disyunción bit a bit entre el contenido de%reg yel contenido almacenado a partir de la posición mem. Elresultado se almacena en memoria a partir de la posiciónmem.

ORs $inm, mem

Realiza la disyunción bit a bit entre inm, codificado conlos bits especificados por el sufijo s con el dato cuyotamaño está especificado por el sufijo s y que estáalmacenado a partir de la posición mem. El resultado sealmacena en memoria a partir de la posición mem.

La disyunción bit a bit significa que ambos operandos deben tener el mismo tamaño y que cada bit del resultado se calculahaciendo la disyunción de los correspondientes bits de ambos operandos. Los flags OF y CF se ponen a cero. Los flags SF, ZF yPF se modifican de acuerdo con el resultado.

A.4.3. XOR: Instrucción de disyunción exclusiva

Instrucción Descripción

XOR %regA, %regB

Realiza la disyunción exclusiva bit a bit del contenidode%regA con el contenido de%regB. Deposita elresultado en%regB.

XOR $inm, %regRealiza la disyunción exclusiva bit a bit entre inm y elcontenido de%reg. Deposita el resultado en%reg.

Page 174: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

174 / 198

Instrucción Descripción

XOR mem, %reg

Realiza la disyunción exclusiva bit a bit entre el contenidoalmacenado en la posición mem y el contenido de%reg.Deposita el resultado en%reg.

XOR %reg, mem

Realiza la disyunción exclusiva bit a bit entre el contenidode%reg y el contenido almacenado a partir de la posiciónmem. El resultado se almacena en memoria a partir de laposición mem.

XORs $inm, mem

Realiza la disyunción exclusiva bit a bit entre inm,codificado con los bits especificados por el sufijo s con eldato cuyo tamaño está especificado por el sufijo s y queestá almacenado a partir de la posición mem. El resultadose almacena en memoria a partir de la posición mem.

La disyunción exclusiva bit a bit significa que ambos operandos deben tener el mismo tamaño y que cada bit del resultado secalcula haciendo la disyunción de los correspondientes bits de ambos operandos. Los flags OF y CF se ponen a cero. Los flagsSF, ZF y PF se modifican de acuerdo con el resultado.

A.4.4. NOT: Instrucción de negación

Instrucción Descripción

NOT %reg Niega bit a bit el contenido de%reg.

NOTs memNiega bit a bit al dato cuyo tamaño está especificado por elsufijo s y que está almacenado a partir de la posición mem.

Esta instrucción no modifica ninguno de los flags de la palabra de estado.

A.5. Instrucciones de desplazamiento

A.5.1. SAL/SAR: Desplazamiento aritmético

Instrucción Descripción

SAL $inm, %reg

Desplaza el contenido de%reg a la izquierda tantasposiciones como indica inm. Para cada desplazamiento, elbit más significativo se carga en el flag CF y el menossignificativo se pone a cero.

SAR $inm, %reg

Desplaza el contenido de%reg a la derecha tantasposiciones como indica inm. Para cada desplazamiento elbit menos significativo se carga en el flag CF y el nuevo bitmás significativo se pone al mismo valor del anterior(extensión de signo).

SAL %cl, %reg

Desplaza el contenido de%reg a la izquierda tantasposiciones como indica el registro%cl. Para cadadesplazamiento, el bit más significativo se carga en el flagCF y el menos significativo se pone a cero.

Page 175: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

175 / 198

Instrucción Descripción

SAR %cl, %reg

Desplaza el contenido de%reg a la derecha tantasposiciones como indica%cl. Para cada desplazamiento elbit menos significativo se carga en el flag CF y el nuevo bitmás significativo se pone al mismo valor del anterior(extensión de signo).

SALs $inm, mem

Desplaza el contenido del dato cuyo tamaño lo especifica elsufijo s y que está almacenado a partir de la posición dememoria mem a la izquierda tantas posiciones como indicainm. Para cada desplazamiento, el bit más significativo delsegundo operando se carga en el flag CF y el menossignificativo del resultado se pone a cero.

SARs $inm, mem

Desplaza el contenido del dato cuyo tamaño lo especifica elsufijo s y que está almacenado a partir de la posición dememoria mem a la derecha tantas posiciones como indicainm. Para cada desplazamiento el bit menos significativodel segundo operando se carga en el flag CF y el nuevo bitmás significativo del resultado se pone al mismo valor delanterior (extensión de signo).

SALs %cl, mem

Desplaza el contenido del dato cuyo tamaño lo especifica elsufijo s y que está almacenado a partir de la posición dememoria mem a la izquierda tantas posiciones como indicael registro%cl. Para cada desplazamiento, el bit mássignificativo del segundo operando se carga en el flag CF yel menos significativo del resultado se pone a cero.

SARs %cl, mem

Desplaza el contenido del dato cuyo tamaño lo especifica elsufijo s y que está almacenado a partir de la posición dememoria mem a la derecha tantas posiciones como indica elregistro%cl. Para cada desplazamiento el bit menossignificativo del segundo operando se carga en el flag CF yel nuevo bit más significativo del resultado se pone almismo valor del anterior (extensión de signo).

El flag CF contiene el valor del último bit que ha sido desplazado. El flag OF se modifica sólo en el caso de desplazamientos de 1bit. Para desplazamientos a izquierda, este flag se pone a cero si los dos bits más significativos del operando antes de desplazarseson ambos cero. En caso contrario se pone a 1. Si el desplazamiento es a la derecha, el valor es siempre cero. Los flags SF, ZF yPF se modifican de acuerdo con el resultado obtenido.

A.5.2. SHL/SHR: Desplazamiento lógico

Instrucción Descripción

SHL $inm, %reg

Desplaza el contenido de%reg a la izquierda tantasposiciones como indica inm. Para cada desplazamiento, elbit más significativo se carga en el flag CF y el menossignificativo se pone a cero.

SHR $inm, %reg

Desplaza el contenido de%reg a la derecha tantasposiciones como indica inm. Para cada desplazamiento elbit menos significativo se carga en el flag CF y el nuevo bitmás significativo se pone a cero.

SHL %cl, %reg

Desplaza el contenido de%reg a la izquierda tantasposiciones como indica el registro%cl. Para cadadesplazamiento, el bit más significativo se carga en el flagCF y el menos significativo se pone a cero.

Page 176: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

176 / 198

Instrucción Descripción

SHR %cl, %reg

Desplaza el contenido de%reg a la derecha tantasposiciones como indica%cl. Para cada desplazamiento elbit menos significativo se carga en el flag CF y el nuevo bitmás significativo se pone a cero.

SHLs $inm, mem

Desplaza el contenido del dato cuyo tamaño lo especifica elsufijo s y que está almacenado a partir de la posición dememoria mem a la izquierda tantas posiciones como indicainm. Para cada desplazamiento, el bit más significativo delsegundo operando se carga en el flag CF y el menossignificativo del resultado se pone a cero.

SHRs $inm, mem

Desplaza el contenido del dato cuyo tamaño lo especifica elsufijo s y que está almacenado a partir de la posición dememoria mem a la derecha tantas posiciones como indicainm. Para cada desplazamiento el bit menos significativodel segundo operando se carga en el flag CF y el nuevo bitmás significativo del resultado se pone a cero.

SHLs %cl, mem

Desplaza el contenido del dato cuyo tamaño lo especifica elsufijo s y que está almacenado a partir de la posición dememoria mem a la izquierda tantas posiciones como indicael registro%cl. Para cada desplazamiento, el bit mássignificativo del segundo operando se carga en el flag CF yel menos significativo del resultado se pone a cero.

SHRs %cl, mem

Desplaza el contenido del dato cuyo tamaño lo especifica elsufijo s y que está almacenado a partir de la posición dememoria mem a la derecha tantas posiciones como indica elregistro%cl. Para cada desplazamiento el bit menossignificativo del segundo operando se carga en el flag CF yel nuevo bit más significativo del resultado se pone a cero.

El flag CF contiene el valor del último bit que ha sido desplazado. El flag OF se modifica sólo en el caso de desplazamientos de 1bit. Para desplazamientos a izquierda, este flag se pone a cero si los dos bits más significativos del operando antes de desplazarseson ambos cero. En caso contrario se pone a 1. Si el desplazamiento es a la derecha, el valor es el bit más significativo del segundooperando. Los flags SF, ZF y PF se modifican de acuerdo con el resultado obtenido.

A.5.3. RCL/RCR: Instrucción de rotación con acarreo

Instrucción Descripción

RCL $inm, %reg

RCR $inm, %reg

Rota el contenido de%reg concatenado con el flag CF a laizquierda (RCL) o derecha (RCR) tantas posiciones comoindica inm. Si el desplazamiento es a la izquierda, paracada desplazamiento el bit más significativo se carga en elflag CF y éste pasa a ser el bit menos significativo. Si eldesplazamiento es a la derecha, para cada desplazamientoel bit menos significativo se carga en el flag CF y éste pasaa ser el bit más significativo.

RCL %cl, %reg

RCR %cl, %reg

Rota el contenido de%reg concatenado con el flag CF a laizquierda (RCL) o derecha (RCR) tantas posiciones comoindica el registro%cl. Si el desplazamiento es a laizquierda, para cada desplazamiento el bit más significativose carga en el flag CF y éste pasa a ser el bit menossignificativo. Si el desplazamiento es a la derecha, paracada desplazamiento el bit menos significativo se carga enel flag CF y éste pasa a ser el bit más significativo.

Page 177: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

177 / 198

Instrucción Descripción

RCLs $inm, mem

RCRs $inm, mem

Rota el dato cuyo tamaño viene especificado por el sufijo sy que está almacenado en memoria a partir de la posiciónmem concatenado con el flag CF a la izquierda (RCL) oderecha (RCR) tantas posiciones como indica inm. Si eldesplazamiento es a la izquierda, para cada desplazamientoel bit más significativo se carga en el flag CF y éste pasa aser el bit menos significativo. Si el desplazamiento es a laderecha, para cada desplazamiento el bit menossignificativo se carga en el flag CF y éste pasa a ser el bitmás significativo.

RCLs %cl, mem

RCRs %cl, mem

Rota el dato cuyo tamaño viene especificado por el sufijo sy que está almacenado en memoria a partir de la posiciónmem concatenado con el flag CF a la izquierda (RCL) oderecha (RCR) tantas posiciones como indica elregistro%cl. Si el desplazamiento es a la izquierda, paracada desplazamiento el bit más significativo se carga en elflag CF y éste pasa a ser el bit menos significativo. Si eldesplazamiento es a la derecha, para cada desplazamientoel bit menos significativo se carga en el flag CF y éste pasaa ser el bit más significativo.

Estas instrucciones hacen que el operando destino, concatenado con el flag de acarreo CF se comporte igual que si tuviese unaestructura circular. Es decir, el bit más significativo pasa al accarreo y éste al menos significativo si se desplaza a izquierda, y alrevés si se desplaza a derecha.

Esta instrucción se utiliza para posicionar un determinado bit de un dato en el bit de acarreo y así poder consultar su valor.Mediante la operación inversa, permite dejar tanto el operando como el flag con su valor anterior.

Aparte del flag CF que almacena uno de los bits del operando, el otro flag que se modifica es OF pero sólo en los casos en losque el desplazamiento es de un bit. Para desplazamientos a izquierda OF contiene el resultado de la disyunción exclusiva entreCF tras el desplazamiento y el bit más significativo del resultado. Para desplazamientos a la derecha, OF es igual a la disyunciónexclusiva de los dos bits más significativos del resultado.

El resto de flags SF, ZF y PF no se modifican.

A.5.4. ROR/ROL: Instrucción de rotación sin acarreo

Instrucción Descripción

ROL $inm, %reg

ROR $inm, %reg

Rota el contenido de%reg a la izquierda (ROL) o derecha(ROR) tantas posiciones como indica inm. Si eldesplazamiento es a la izquierda, para cada desplazamientoel bit más significativo pasa a ser el menos significativo. Siel desplazamiento es a la derecha, para cadadesplazamiento el bit menos significativo pasa a ser el mássignificativo.

ROL %cl, %reg

ROR %cl, %reg

Rota el contenido de%reg a la izquierda (ROL) o derecha(ROR) tantas posiciones como indica el registro%cl. Si eldesplazamiento es a la izquierda, para cada desplazamientoel bit más significativo pasa a ser el bit menos significativo.Si el desplazamiento es a la derecha, para cadadesplazamiento el bit menos significativo pasa a ser el bitmás significativo.

Page 178: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

178 / 198

Instrucción Descripción

ROLs $inm, mem

RORs $inm, mem

Rota el dato cuyo tamaño viene especificado por el sufijo sy que está almacenado en memoria a partir de la posiciónmem a la izquierda (ROL) o derecha (ROR) tantasposiciones como indica inm. Si el desplazamiento es a laizquierda, para cada desplazamiento el bit más significativopasa a ser el bit menos significativo. Si el desplazamientoes a la derecha, para cada desplazamiento el bit menossignificativo pasa a ser el bit más significativo.

ROLs %cl, mem

RORs %cl, mem

Rota el dato cuyo tamaño viene especificado por el sufijo sy que está almacenado en memoria a partir de la posiciónmem a la izquierda (ROL) o derecha (ROR) tantasposiciones como indica el registro%cl. Si eldesplazamiento es a la izquierda, para cada desplazamientoel bit más significativo pasa a ser el bit menos significativo.Si el desplazamiento es a la derecha, para cadadesplazamiento el bit menos significativo pasa a ser el bitmás significativo.

Estas instrucciones hacen que el operando destino se comporte igual que si tuviese una estructura circular. Es decir, el bit mássignificativo pasa a ser el bit de menos peso si se desplaza a izquierda, y al revés si se desplaza a derecha.

El flag CF almacena el bit más significativo si se desplaza a izquierda, y el menos significativo si se desplaza a derecha. El flag OFse modifica sólo en los casos en los que el desplazamiento es de un bit. Para desplazamientos a izquierda OF contiene el resultadode la disyunción exclusiva entre CF tras el desplazamiento y el bit más significativo del resultado. Para desplazamientos a laderecha, OF es igual a la disyunción exclusiva de los dos bits más significativos del resultado.

El resto de flags SF, ZF y PF no se modifican.

A.6. Instrucciones de salto

A.6.1. JMP: Instrucción de salto incondicional

Instrucción Descripción

JMP memPasa a ejecutar a continuación la instrucción almacenada apartir de la posición de memoria mem.

JMP *%regPasa a ejecutar a continuación la instrucción almacenada apartir de la posición de memoria en%reg

Esta instrucción simplemente cambia la secuencia de ejecución del procesador que ejecuta la instrucción indicada en la posiciónde memoria dada como operando. El uso más común es con una etiqueta como operando, que es donde pasa a ejecutar elprocesador. Si el segundo operando es un registro con el prefijo * el valor del registro se carga en el contador de programa y seejecuta la instrucción en la posición de memoria con ese valor.

A.6.2. Jcc: Instrucciones de salto condicional

Page 179: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

179 / 198

Instrucción Condición Descripción Instrucción Condición Descripción

JA mem

JNBE mem

CF = 0 y ZF = 0

Salto si mayor,salto si no menoro igual (sinsigno)

JBE mem

JNA mem

CF = 1 ó ZF = 1Salto si menor oigual, salto si nomayor (sin signo)

JAE mem

JNB mem

CF = 0Salto si mayor oigual, salto si nomenor (sin signo)

JB mem

JNAE mem

CF = 1

Salto si menor,salto si no mayoro igual (sinsigno)

JE mem

JZ mem

ZF = 1 Salto si igual,salto si cero.

JNE mem

JNZ mem

ZF = 0 Salto si diferente,salto si no cero.

JG mem

JNLE mem

ZF = 0 y SF = OFSalto si mayor, sino menor o igual(con signo)

JLE mem

JNG mem

ZF = 1 ó SF !=OF

Salto si menor oigual, si nomayor (consigno)

JGE mem

JNL mem

SF = OF

Salto si mayor oigual, si nomenor (consigno)

JL mem

JNGE mem

SF != OFSalto si menor, sino mayor o igual(con signo)

JC mem CF = 1 Salto si acarreoes uno JNC mem CF = 0 Salto si acarreo

es cero

JCXZ mem %cx = 0Salto siregistro%cx escero.

JECXZ mem %ecx = 0Salto siregistro%ecx escero.

JO mem OF = 1Salto si el bit dedesbordamientoes uno.

JNO mem OF = 0Salto si el bit dedesbordamientoes cero.

JPO mem

JNP mem

PF = 0Salto si paridadimpar, si noparidad.

JPE mem

JP mem

PF = 1 Salto si paridadpar, si paridad.

JS mem SF = 1 Salto si positivo. JNS mem SF = 0 Salto si negativo.

A.6.3. CALL: Instrucción de llamada a subrutina

Instrucción Descripción

CALL mem

Invoca la subrutina cuya primera instrucción está en laposición de memoria mem. Se salva el contador deprograma en la cima de la pila.

Page 180: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

180 / 198

Instrucción Descripción

CALLs *%regInvoca la subrutina cuya primera instrucción está en laposición de memoria contenida en el registro%reg.

El efecto relevante de esta instrucción es que deposita en la cima de la pila la dirección de retorno, o lo que es lo mismo, ladirección de la instrucción que sigue a esta en el flujo de ejecución. Esta instrucción no modifica los flags de la palabra de estado.

A.6.4. RET: Instrucción de retorno de subrutina

Instrucción Descripción

RET

Retorna la ejecución a la instrucción cuya dirección estáalmacenada en la cima de la pila. Esta dirección se saca dela pila.

El aspecto relevante de esta instrucción es que supone que la dirección a la que debe retornar está almacenada en la cima de lapila. Esta instrucción no modifica los flags de la palabra de estado.

A.7. Instrucciones de comparación y comprobación

A.7.1. CMP: Instrucción de comparación

Instrucción Descripción

CMP %regA, %regBRealiza la operación%regB -%regA y modifica los flagscon el resultado que no se almacena en lugar alguno.

CMP $inm, %regRealiza la operación%reg - inm y modifica los flags conel restulado que no se almacena en lugar alguno.

CMP mem, %regRealiza la operación mem -%reg y modifica los flags conel restulado que no se almacena en lugar alguno.

CMP %reg, memRealiza la operación mem -%reg y modifica los flags conel resultado que no se almacena en lugar alguno.

CMPs $inm, mem

Resta el dato almacenado a partir de la posición dememoria mem y cuyo tamaño está especificado por el sufijos del valor inm codificado con tantos bits como indica elsufijo s. Se modifican los flags con el resultado de estaresta que no se almacena en lugar alguno.

El efecto de esta instrucción se refleja únicamente en los flags de la palabra de estado. Estos flags se pueden utilizar para, porejemplo, cambiar el flujo de ejecución mediante una instrucción de salto condicional.

A.7.2. TEST: Instrucción de comprobación

Page 181: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

181 / 198

Instrucción Descripción

TEST %regA, %regB

Realiza la conjunción bit a bit entre%regB y%regA ymodifica los flags con el resultado que no se almacena enlugar alguno.

TEST $inm, %reg

Realiza la conjunción bit a bit entre%reg e inm ymodifica los flags con el restulado que no se almacena enlugar alguno.

TEST mem, %reg

Realiza la conjunción bit a bit entre mem y%reg ymodifica los flags con el restulado que no se almacena enlugar alguno.

TEST %reg, mem

Realiza la conjunción bit a bit entre mem y%reg ymodifica los flags con el resultado que no se almacena enlugar alguno.

TESTs $inm, mem

Realiza la conjunción bit a bit entre el dato almacenado apartir de la posición de memoria mem y cuyo tamaño estáespecificado por el sufijo s y el valor inm codificado contantos bits como indica el sufijo s. Se modifican los flagscon el resultado de esta resta que no se almacena en lugaralguno.

El efecto de esta instrucción se refleja únicamente en los flags de la palabra de estado. Los flags OF y CF se ponen a cero. Losflags SF, ZF y PF se modifican de acuerdo con el resultado.

Page 182: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

182 / 198

Apéndice B

El depurador

Uno de los principales problemas al escribir programas son los errores de ejecución. Compilar un programa no es garantíasuficiente de que funciona de la manera prevista. Es más, el ciclo de desarrollo de un programa está ocupado, en su mayoríapor las tareas de diagnosticar y corregir los errores de ejecución. A los errores de ejecución en programas en inglés se les sueledenominar bugs (bichos).

El origen de la utilización del término bug para describir los errores en un program es un poco confuso, pero hay una referenciadocumentada a la que se le suele atribuir este mérito.

La invención del término se atribuye generalmente a la ingeniera Grace Hopper que en 1946 estaba en el laboratorio de compu-tación de la universidad de Harvard trabajando en los ordenadores con nombre Mark II y Mark III. Los operadores descubrieronque la causa de un error detectado en el Mark II era una polilla que se había quedado atrapada entre los contactos de un relé (poraquel entonces el elemento básido de un ordenador) que a su vez era parte de la lógica interna del ordenador. Estos operadoresestaban familiarizados con el término bug e incluso pegaron el insecto en su libro de notas con la anotación ‘First actual case ofbug being found’ (primer caso en el que realmente se encuentra un bug) tal y como ilustra la figura B.1.

Page 183: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

183 / 198

Figura B.1: Primer caso en el que realmente se encuentra un bug (Fuente: U.S. Naval Historical Center Photograph)

Hoy en día, los métodos que se utilizan para depurar los errores de un programa son múltiples y con diferentes niveles de eficacia.El método consistente en insertar líneas de código que escriben en pantalla mensajes es quizás el más ineficiente de todos ellos.En realidad lo que se precisa es una herramienta que permita ejecutar de forma controlada un programa, que permita suspenderla ejecución en cualquier punto para poder realizar comprobaciones, ver el contenido de las variables, etc.

Esta herramienta se conoce con el nombre de depurador o, su término inglés, debugger. El depurador es un ejecutable cuya misiónes permitir la ejecución controlada de un segundo ejecutable. Se comporta como un envoltorio dentro del cual se desarrolla unaejecución normal de un programa, pero a la vez permite realizar una serie de operaciones específicas para visualizar el entornode ejecución en cualquier instante.

Más concretamente, el depurador permite:

ejecutar un programa línea a línea

detener la ejecución temporalmente en una línea de código concreta

detener temporalmente la ejecución bajo determinadas condiciones

Page 184: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

184 / 198

visualizar el contenido de los datos en un determinado momento de la ejecución

cambiar el valor del entorno de ejecución para poder ver su efecto de una corrección en el programa

Uno de los depuradores más utilizados en entornos Linux es gdb (Debugger de GNU). En este documento se describen loscomandos más relevantes de este depurador para ser utilizados con un programa escrito en C. Todos los ejemplos utilizados enel resto de esta sección se basan en el programa cuyo código fuente se muestra en la Tabla B.1 y que se incluye en el ficherogdbuse.s

12345678910111213141516171819202122232425262728

29

.data # Comienza ←↩sección de datos

nums: .int 2, 3, 2, 7, 5, 4, 9# Secuencia ←↩

de números a imprimirtamano: .int 7 # Tamaño de ←↩

la secuenciaformato:.string "%d\n" # String ←↩

para imprimir un número.text # Comienza ←↩

la sección de código.globl main # main es un ←↩

símbolo globalmain: push %ebp # Bloque de ←↩

activaciónmov %esp, %ebppush %eax # Guardar ←↩

copia de los registros en la pilapush %ebxpush %ecxpush %edxmov $0, %ebx

bucle: cmp %ebx, tamanoje terminapush nums(,%ebx,4) # pone el ←↩

número en la pilapush $formato # pone el ←↩

formato en la pilacall printf # imprime ←↩

los datos que recibeadd $8, %esp # borra los ←↩

datos de la cima de la pilainc %ebxjmp bucle

termina:pop %edx # restaurar ←↩el valor de los registros

pop %ecxpop %ebxpop %eaxmov %ebp, %esp # Deshacer ←↩

bloque de activaciónpop %ebpret # termina el ←↩

programa

Tabla B.1: Programa en ensamblador utilizado como ejemplo

Page 185: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

185 / 198

B.1. Arranque y parada del depurador

Para que un programa escrito en ensamblador pueda ser manipulado por gdb es preciso realizar una compilación que incluyacomo parte del ejecutable, un conjunto de datos adicionales. Esto se consigue incluyendo la opción -gstabs+ al invocar elcompilador:

shell$ gcc -gstabs+ -o gdbuse gdbuse.s

Si el programa se ha escrito correctamente este comando ha generado el fichero ejecutable con nombre gdbuse. Una vez estefichero se invoca el depurador con el comando:

shell$ gdb gdbuse

Tras arrancar el depurador se muestra por pantalla un mensaje seguido del prompt (gdb):

shell$ gdb gdbuseGNU gdb Red Hat Linux (6.0post-0.20040223.19rh)Copyright 2004 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/ ←↩

lib/tls/libthread_db.so.1".

(gdb)

En este instante, el programa depurador ha arrancado, pero la ejecución del programa gdbuse (que se ha pasado como primerargumento) todavía no. La interacción con el depurador se realiza a través de comandos introducidos a continuación del prompt,de forma similar a como se proporcionan comandos a un shell o intérprete de comandos en Linux.

Para arrancar la ejecución del programa se utiliza el comando run (o su abreviatura r). Tras introducir este comando, el programase ejecuta de forma normal y se muestra por pantalla de nuevo el prompt (gdb). Por ejemplo:

(gdb) rStarting program: /home/test/gdbuse2327549

Program exited normally.

(gdb)

En el ejemplo, se puede comprobar como el programa termina correctamenta (tal y como denota el mensaje que aparece porpantalla). Cuando se produce un error en la ejecución, el depurador se detiene y muestra de nuevo el prompt.

Si se desea detener un programa mientras se está ejecutando se debe pulsar Crtl-C (la tecla control, y mientras se mantienepulsada, se pulsa C). La interrupción del programa es capturada por el depurador, y el control lo retoma el intérprete de comandosde gdb. En este instante, la ejecución del programa ha sido detenida pero no terminada. Prueba de ello, es que la ejecución puedecontinuarse mediante el comando continue (que se puede abreviar simplemente con la letra c).

Page 186: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

186 / 198

Para salir del depurador se utiliza el comando quit (abreviado por la letra q). Si se pretende terminar la sesión del depuradormientras el programa está en ejecución se pide confirmación para terminar dicha ejecución.

(gdb) qThe program is running. Exit anyway? (y or n) y

shell$

El comando help muestra la información referente a todos los comandos y sus opciones. Si se invoca sin parámetros, se mues-tran las categorías en las que se clasifican los comandos. El comando help seguido del nombre de una categoría, proporcionainformación detallada sobre sus comandos. Si se invoca seguido de un comando, describe su utilización.

B.2. Visualización de código

El código fuente del programa en ejecución se puede mostrar por pantalla mediante el comando list (abreviado l). Sin opciones,este comando muestra la porción de código alrededor de la línea que está siendo ejecutada en el instante en el que está detenido elprograma. Si el programa no está en ejecución, se muestra el código a partir de la etiqueta main. El comando list acepta opcionespara mostrar una línea en concreto, una línea en un fichero, una etiqueta en un fichero, e incluso el código almacenado en unadirección de memoria completa. El comando help list muestra todas las opciones posibles.

(gdb) l main3 # Secuencia de números a imprimir4 tamano: .int 7 # Tamaño de la secuencia5 formato:.string "%d\n" # String para imprimir un número6 .text # Comienza la sección de código7 .globl main # main es un símbolo global8 main: push %ebp # Bloque de activación9 mov %esp, %ebp10 push %eax # Guardar copia de los registros en la pila11 push %ebx12 push %ecx

(gdb)

B.3. Ejecución controlada de un programa

Aparte de detener la ejecución de un programa con Crtl-C, lo más útil es detener la ejecución en una línea concreta del código.Para ello es preciso insertar un punto de parada (en inglés breakpoint). Dicho punto es una marca que almacena el depurador, ycada vez que la ejecución del programa pasa por dicho punto, suspende la ejecución y devuelve el control al usuario. Para insertarun punto de parada se utiliza el comando break (abreviado b) seguido de la línea en la que se desea introducir.

Page 187: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

187 / 198

(gdb) l 149 mov %esp, %ebp10 push %eax # Guardar copia de los registros en la pila11 push %ebx12 push %ecx13 push %edx14 mov $0, %ebx15 bucle: cmp %ebx, tamano16 je termina17 push nums(,%ebx,4) # pone el número en la pila18 push $formato # pone el formato en la pila(gdb) b 14Breakpoint 1 at 0x8048377: file gdbuse.s, line 14.

(gdb)

Se pueden introducir tantos puntos de parada como sean necesarios en diferentes lugares del código. El depurador asigna unnúmero a cada uno de ellos comenzando por el 1. En la última línea del mensaje anterior se puede ver como al punto introducidoen la línea 14 del fichero gdbuse.s se le ha asignado el número 1.

El comando info breakpoints (o su abreviatura info b) muestra por pantalla la lista de puntos de parada que contiene el depurador.

(gdb) l 2116 je termina17 push nums(,%ebx,4) # pone el número en la pila18 push $formato # pone el formato en la pila19 call printf # imprime los datos que recibe20 add $8, %esp # borra los datos de la cima de la pila21 inc %ebx22 jmp bucle23 termina:pop %edx # restaurar el valor de los registros24 pop %ecx25 pop %ebx(gdb) b 21Breakpoint 2 at 0x8048398: file gdbuse.s, line 21.(gdb) info breakpointsNum Type Disp Enb Address What1 breakpoint keep y 0x08048377 gdbuse.s:142 breakpoint keep y 0x08048398 gdbuse.s:21

(gdb)

Los puntos de parada se pueden introducir en cualquier momento de la ejecución de un proceso. Una vez introducidos, si secomienza la ejecución del programa mediante el comando run (o su abreviatura r), ésta se detiene en cuanto se ejecuta una líneacon un punto de parada.

Page 188: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

188 / 198

(gdb) rStarting program: /home/test/gdbuse

Breakpoint 1, main () at gdbuse.s:1414 mov $0, %ebx(gdb) cContinuing.2

Breakpoint 2, bucle () at gdbuse.s:2121 inc %ebx

(gdb)

Nótese que el depurador primero se ha detenido en el punto de parada 1, tras introducir el comando continue se ha detenido enel punto de parada 2.

Cada punto de parada puede ser temporalmente desactivado/activado de manera independiente. Los comandos enable y disableseguido de un número de punto de parada activan y desactivan respectivamente dichos puntos.

Para reanudar la ejecución del programa previamente suspendida hay tres comandos posibles. El primero que ya se ha visto escontinue (o c). Este comando continua la ejecución del programa y no se detendrá hasta que se encuentre otro punto de parada,se termine la ejecución, o se produzca un error. El segundo comando para continuar la ejecución es stepi (o su abreviatura si).Este comando ejecuta únicamente la instrucción en la que está detenido el programa y vuelve de nuevo a suspender la ejecución.

(gdb) rThe program being debugged has been started already.Start it from the beginning? (y or n) y

Starting program: /home/test/gdbuse

Breakpoint 1, main () at gdbuse.s:1414 mov $0, %ebx(gdb) sibucle () at gdbuse.s:1515 bucle: cmp %ebx, tamano(gdb) si16 je termina

(gdb)

Con la utilización de este comando se puede conseguir ejecutar un programa ensamblador instrucción a instrucción de formaque se pueda ver qué está sucediendo en los registros del procesador y en los datos en memoria. Mediante la combinación delmecanismo de puntos de parada y el comando stepi se puede ejecutar un programa hasta un cierto punto, y a partir de él irinstrucción a instrucción. Este proceso es fundamental para detectar los errores en los programas.

El comando stepi tiene un inconveniente. Cuando la instrucción a ejecutar es una llamada a subrutina (por ejemplo la instruccióncall printf), el depurador ejecuta la instrucción call y se detiene en la primera instrucción de la subrutina. Este compor-tamiento es deseable siempre y cuando se quiera ver el código de la subrutina, pero si dicho código pertenece a una librería delsistema, lo que se necesita es un comando que permita ejecutar la llamada a la subrutina entera y detenerse en la instrucción quele sigue. Esto se puede conseguir si, al estar a punto de ejecutar una instrucción call se utiliza el comando nexti en lugar destepi.

Page 189: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

189 / 198

(gdb) rThe program being debugged has been started already.Start it from the beginning? (y or n) y

Starting program: /home/bin/gdbuse

Breakpoint 1, main () at gdbuse.s:1414 mov $0, %ebx(gdb) sibucle () at gdbuse.s:1515 bucle: cmp %ebx, tamano(gdb) si16 je termina(gdb) si17 push nums(,%ebx,4) # pone el número en la pila(gdb) sibucle () at gdbuse.s:1818 push $formato # pone el formato en la pila(gdb) sibucle () at gdbuse.s:1919 call printf # imprime los datos que recibe(gdb) ni220 add $8, %esp # borra los datos de la cima de la pila

(gdb)

En general, cuando se produce un error en un programa ensamblador, mediante la utilización de los puntos de parada se permitellegar al programa al lugar aproximado del código en el que se supone que está el error, y luego mediante la utilización de stepi seejecuta instrucción a instrucción teniendo cuidado de utilizar nexti cuando se quiera ejecutar una instrucción call que incluyala llamada entera.

B.4. Visualización de datos

Los comandos descritos hasta ahora permiten una ejecución controlada de un programa, pero cuando el depurador es realmenteeficiente es cuando hay que localizar un error de ejecución. Generalmente, ese error se manifiesta como una terminación abrup-ta (por ejemplo segmentation fault). Cuando el programa se ejecuta desde el depurador, esa terminación retorna el control aldepurador con lo que es posible utilizar comandos para inspeccionar el estado en el que ha quedado el programa.

Uno de los comandos más útiles del depurador es print (o su abreviatura p). Como argumento recibe una expresión, y su efectoes imprimir el valor resultante de evaluar dicha expresión. Este comando puede recibir el nombre de cualquier símbolo que estévisible en ese instante en la ejecución del programa. El contenido de uno de estos símbolos se muestra por pantalla simplementeescribiendo el comando print seguido del nombre.

Page 190: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

190 / 198

(gdb) rThe program being debugged has been started already.Start it from the beginning? (y or n) y

Starting program: /home/bin/gdbuse

Breakpoint 1, main () at gdbuse.s:1414 mov $0, %ebx(gdb) p tamano$7 = 7

(gdb)

Aparte de nombres de etiquetas que apuntan a datos, print acepta expresiones que se refieren a los registros del procesador:$eax, $ebx, etc.

Breakpoint 1, main () at gdbuse.s:1414 mov $0, %ebx(gdb) p tamano$7 = 7(gdb) p $eax$8 = 0(gdb) p $ebx$9 = 9105372(gdb) p/x $ebx$10 = 0x8aefdc

(gdb)

Nótese que el último comando print tiene el sufijo /x que hace que el resultado se muestre en hexadecimal, en lugar de decimal.Si se quiere ver el contenido de todos los registros del procesador se puede utilizar el comando info registers.

(gdb) info registerseax 0x0 0ecx 0xfefff5ec -16779796edx 0xfefff5e4 -16779804ebx 0x8aefdc 9105372esp 0xfefff548 0xfefff548ebp 0xfefff558 0xfefff558esi 0x1 1edi 0x8b10dc 9113820eip 0x8048377 0x8048377eflags 0x200246 2097734cs 0x73 115ss 0x7b 123ds 0x7b 123es 0x7b 123fs 0x0 0gs 0x33 51

(gdb)

Nótese que para cada registro se muestra su valor en hexadecimal seguido por su representación en decimal. No todos los registros

Page 191: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

191 / 198

que muestra este comando son manipulables desde un programa ensamblador, tan sólo los ocho primeros.

El comando print permite igualmente visualizar arrays de valores consecutivos en memoria. Para ello es preciso especificar enel comando el tipo de datos que contiene el array y su longitud. El formato utilizado es incluir entre paréntesis el tipo seguidopor el tamaño entre corchetes. En el programa dado como ejemplo el comando para imprimir los siete números enteros que sedefinen en la etiqueta nums es:

(gdb) p/x (int[7])nums$13 = {0x2, 0x3, 0x2, 0x7, 0x5, 0x4, 0x9}

(gdb)

Si lo que se necesita es visualizar los bytes almacenados en un lugar concreto de memoria, el comando examine (o su abreviatura‘x’) imprime una determinada porción de memoria por pantalla. La sintaxis de este comando es ‘x/NFU dirección’. Las letrasNFU representan opciones del comando. La N representa un entero que codifica el número de unidades de información enmemoria a mostrar. La F representa el formato en el que se muestran los datos (al igual que el comando print, la ‘x’ quiere decirhexadecimal). La letra U representa el tamaño de las unidades a mostrar. Sus posibles valores son ‘b’ para bytes, ‘h’ para palabrasde 2 bytes, ‘w’ para palabras de 4 bytes y ‘g’ para palabras de ocho bytes.

La dirección a partir de la cual se muestra el contenido se puede dar como una constante en hexadecimal, o como el nombre deuna etiqueta precedido del carácter ‘&’. Por ejemplo, para mostrar el contenido de las 7 palabras de 4 bytes almacenadas a partirde la etiqueta nums el comando es:

(gdb) x/7xw &nums0x804957c >nums<: 0x00000002 0x00000003 0x00000002 0x000000070x804958c >nums+16<: 0x00000005 0x00000004 0x00000009

(gdb)

Este comando se puede utilizar para mostrar el contenido de una porción de memoria a la que apunta un determinado registro. Porejemplo, para mostrar las cuatro palabras de memoria almacenadas en la cima de la pila se puede utilizar el siguiente comando:

(gdb) x/16xb $esp0xfefff548: 0xe4 0xf5 0xff 0xfe 0xec 0xf5 0xff 0xfe0xfefff550: 0xdc 0xef 0x8a 0x00 0x00 0x00 0x00 0x00

(gdb)

Además de visualizar datos en registros o memoria, el depurador permite también manipular estos datos mientras el programaestá detenido. El comando set permite la asignación de un valor numérico tanto a porciones de memoria como a registros. Paraasignar el valor 10 al registro %eax se utiliza el comando:

(gdb) set $eax=10(gdb) p $eax$14 = 10

(gdb)

Este comando es útil cuando se detecta un valor erróneo en un registro y se puede corregir para mostrar si el programa puedecontinuar normalmente.

Page 192: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

192 / 198

Al igual que se permite modificar datos en registros, también se pueden modificar datos en memoria. Para ello es necesarioespecificar el tipo de dato que se está almacenando entre llaves seguido de la dirección de memoria. De esta forma se especificadónde almacenar el valor que se proporciona a continuación tras el símbolo de igual. Por ejemplo:

(gdb) set {int}0x83040 = 4

(gdb)

El comando anterior almacena el valor 4 en la posición de memoria cuya dirección es 0x83040 y almacena 4 bytes porque serefiere a ella como un entero.

B.5. Ejercicios

Para la realización de los siguientes ejercicios se utiliza el código fuente utilizado como ejemplo, mostrado en la Tabla B.1 ycontenido en el fichero gdbuse.s. Se supone que el programa ha sido compilado, el ejecutable producido y el depurador arrancado.

1. ¿Qué comando hay que utilizar para mostrar por pantalla todos los bytes que codifican el string con nombre formato?

¿Cuál es el valor del último byte?

2. Se sabe que las instrucciones del tipo push :registro: se codifican mediante un único byte y mov :registro-:, :registro: mediante dos bytes. Utilizando únicamente el depurador, decir cuál es el código hexadecimal de lassiguientes instrucciones:

push %ebppush %eaxpush %ebxpush %ecxpush %edx

3. Situar un punto de parada en la instrucción call printf. ¿Qué comando es necesario para mostrar por pantalla el valorque deposita en la cima de la pila la instrucción push $formato?

4. Introducir un punto de parada en la línea 10 del código (en la instrucción push%eax). Mostrar por pantalla mediante elcomando print el valor de los registros%eax,%ebx,%ecx y%edx. Apuntar estos valores.

A continuación introducir un segundo punto de parada en la línea 14 (en la instrucción mov $0,%ebx). Mediante elcomando continue continuar la ejecución hasta ese punto.

¿Qué comando hay que utilizar para mostrar por pantalla el contenido de las cuatro palabras de memoria que se encuentranen la cima de la pila? Comprobar que estos valores son idénticos a los mostrados en el primer punto de parada.

5. La instrucción inc%ebx aumenta el valor de dicho registro en una unidad. Este registro contiene el índice del siguienteelemento a imprimir. Poner un punto de parada en la instrucción siguiente a esta y con el programa detenido modificar elvalor de este registro con un número entre cero y seis (ambos inclusive). Explica qué es lo que sucede y por qué.

6. Utilizando la ejecución instrucción a instrucción que permite el depurador, ¿qué instrucción se ejecuta justo antes de lainstrucción pop%edx?

7. La instrucción push nums(,%ebx,4) deposita un cierto valor en la pila. Introducir un punto de parada en la siguienteinstrucción, y una vez detenido el programa, poner en la cima de la pila otro número arbitrario mediante el comando set.Explica qué efecto tiene esto y por qué.

Page 193: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

193 / 198

B.6.

Introducir todos los valores en hexadecimal y con el prefijo 0x. Responder a todas las preguntas antes de pulsar el botón de envíoal final del formulario.

0. ¿Qué comando hay que utilizar para mostrar por pantalla todos los bytes que codifican el string con nombreformato? text IntroToGdb:A1_stringCod 16 16

¿Cuál es el valor del último byte? text IntroToGdb:A2_stringLastByte 16 16

0. Se sabe que las instrucciones del tipo push :registro: se codifican mediante un único byte y mov:registro:, :registro: mediante dos bytes. Utilizando únicamente el depurador, decir cuál es el códigohexadecimal de las siguientes instrucciones:

push %ebp text IntroToGdb:B1_push 16 16push %eax text IntroToGdb:B2_push 16 16push %ebx text IntroToGdb:B3_push 16 16push %ecx text IntroToGdb:B4_push 16 16push %edx text IntroToGdb:B5_push 16 16

0. Situar un punto de parada en la instrucción call printf. ¿Qué comando es necesario para mostrar por pantallael valor que deposita en la cima de la pila la instrucción push $formato? text IntroToGdb:C_pushformat 16 16

0. ¿Qué comando hay que utilizar para mostrar por pantalla el contenido de las cuatro palabras de memoria que seencuentran en la cima de la pila? Comprobar que estos valores son idénticos a los mostrados en el primer punto deparada. text IntroToGdb:D_stackTop 16 16

0. La instrucción inc%ebx aumenta el valor de dicho registro en una unidad. Este registro contiene el índice delsiguiente elemento a imprimir. Poner un punto de parada en la instrucción siguiente a esta y con el programadetenido modificar el valor de este registro con un número entre cero y seis (ambos inclusive). Explica qué es lo quesucede y por qué.

IntroToGdb:E_arrayindex 80 10

0. Utilizando la ejecución instrucción a instrucción que permite el depurador, ¿qué instrucción se ejecuta justo antesde la instrucción pop%edx? text IntroToGdb:F_beforepop 16 16

0. La instrucción push nums(,%ebx,4) deposita un cierto valor en la pila. Introducir un punto de parada en lasiguiente instrucción, y una vez detenido el programa, poner en la cima de la pila otro número arbitrario mediante elcomando set. Explica qué efecto tiene esto y por qué.

IntroToGdb:G_modifyvalue 80 10

Page 194: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

194 / 198

Apéndice C

Licencia Creative Commons

Reconocimiento-NoComercial-CompartirIgual 2.5 España

CREATIVE COMMONS CORPORATION NO ES UN DESPACHO DE ABOGADOS Y NO PROPORCIONA SERVICIOSJURÍDICOS. LA DISTRIBUCIÓN DE ESTA LICENCIA NO CREA UNA RELACIÓN ABOGADO-CLIENTE. CREATIVECOMMONS PROPORCIONA ESTA INFORMACIÓN TAL CUAL (ON AN "AS-IS" BASIS). CREATIVE COMMONS NOOFRECE GARANTÍA ALGUNA RESPECTO DE LA INFORMACIÓN PROPORCIONADA, NI ASUME RESPONSABILI-DAD ALGUNA POR DAÑOS PRODUCIDOS A CONSECUENCIA DE SU USO.

Licencia

LA OBRA (SEGÚN SE DEFINE MÁS ADELANTE) SE PROPORCIONA BAJO LOS TÉRMINOS DE ESTA LICENCIAPÚBLICA DE CREATIVE COMMONS ("CCPL" O "LICENCIA"). LA OBRA SE ENCUENTRA PROTEGIDA POR LA LEYESPAÑOLA DE PROPIEDAD INTELECTUAL Y/O CUALESQUIERA OTRAS NORMAS RESULTEN DE APLICACIÓN.QUEDA PROHIBIDO CUALQUIER USO DE LA OBRA DIFERENTE A LO AUTORIZADO BAJO ESTA LICENCIA O LODISPUESTO EN LAS LEYES DE PROPIEDAD INTELECTUAL.

MEDIANTE EL EJERCICIO DE CUALQUIER DERECHO SOBRE LA OBRA, USTED ACEPTA Y CONSIENTE LAS LI-MITACIONES Y OBLIGACIONES DE ESTA LICENCIA. EL LICENCIADOR LE CEDE LOS DERECHOS CONTENIDOSEN ESTA LICENCIA, SIEMPRE QUE USTED ACEPTE LOS PRESENTES TÉRMINOS Y CONDICIONES.

1. Definiciones

a. La "obra" es la creación literaria, artística o científica ofrecida bajo los términos de esta licencia.

b. El "autor" es la persona o la entidad que creó la obra.

c. Se considerará "obra conjunta" aquella susceptible de ser incluida en alguna de las siguientes categorías:

1. "Obra en colaboración", entendiendo por tal aquella que sea resultado unitario de la colaboración de varios autores.

2. "Obra colectiva", entendiendo por tal la creada por la iniciativa y bajo la coordinación de una persona natural ojurídica que la edite y divulgue bajo su nombre y que esté constituida por la reunión de aportaciones de diferentesautores cuya contribución personal se funde en una creación única y autónoma, para la cual haya sido concebida sinque sea posible atribuir separadamente a cualquiera de ellos un derecho sobre el conjunto de la obra realizada.

3. "Obra compuesta e independiente", entendiendo por tal la obra nueva que incorpore una obra preexistente sin lacolaboración del autor de esta última.

d. Se considerarán "obras derivadas" aquellas que se encuentren basadas en una obra o en una obra y otras preexistentes,tales como: las traducciones y adaptaciones; las revisiones, actualizaciones y anotaciones; los compendios, resúmenes yextractos; los arreglos musicales y, en general, cualesquiera transformaciones de una obra literaria, artística o científica,salvo que la obra resultante tenga el carácter de obra conjunta en cuyo caso no será considerada como una obra derivada alos efectos de esta licencia. Para evitar la duda, si la obra consiste en una composición musical o grabación de sonidos, lasincronización temporal de la obra con una imagen en movimiento ("synching") será considerada como una obra derivadaa los efectos de esta licencia.

Page 195: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

195 / 198

e. Tendrán la consideración de "obras audiovisuales" las creaciones expresadas mediante una serie de imágenes asociadas,con o sin sonorización incorporada, así como las composiciones musicales, que estén destinadas esencialmente a sermostradas a través de aparatos de proyección o por cualquier otro medio de comunicación pública de la imagen y delsonido, con independencia de la naturaleza de los soportes materiales de dichas obras.

f. El "licenciador" es la persona o la entidad que ofrece la obra bajo los términos de esta licencia y le cede los derechos deexplotación de la misma conforme a lo dispuesto en ella.

g. "Usted" es la persona o la entidad que ejercita los derechos cedidos mediante esta licencia y que no ha violado previamentelos términos de la misma con respecto a la obra, o que ha recibido el permiso expreso del licenciador de ejercitar losderechos cedidos mediante esta licencia a pesar de una violación anterior.

h. La "transformación" de una obra comprende su traducción, adaptación y cualquier otra modificación en su forma dela que se derive una obra diferente. Cuando se trate de una base de datos según se define más adelante, se considerarátambién transformación la reordenación de la misma. La creación resultante de la transformación de una obra tendrá laconsideración de obra derivada.

i. Se entiende por "reproducción" la fijación de la obra en un medio que permita su comunicación y la obtención de copiasde toda o parte de ella.

j. Se entiende por "distribución" la puesta a disposición del público del original o copias de la obra mediante su venta,alquiler, préstamo o de cualquier otra forma.

k. Se entenderá por "comunicación pública" todo acto por el cual una pluralidad de personas pueda tener acceso a la obra sinprevia distribución de ejemplares a cada una de ellas. No se considerará pública la comunicación cuando se celebre dentrode un ámbito estrictamente doméstico que no esté integrado o conectado a una red de difusión de cualquier tipo. A efectosde esta licencia se considerará comunicación pública la puesta a disposición del público de la obra por procedimientosalámbricos o inalámbricos, incluida la puesta a disposición del público de la obra de tal forma que cualquier persona puedaacceder a ella desde el lugar y en el momento que elija.

l. La "explotación" de la obra comprende su reproducción, distribución, comunicación pública y transformación.

m. Tendrán la consideración de "bases de datos" las colecciones de obras ajenas, de datos o de otros elementos independientescomo las antologías y las bases de datos propiamente dichas que por la selección o disposición de sus contenidos constitu-yan creaciones intelectuales, sin perjuicio, en su caso, de los derechos que pudieran subsistir sobre dichos contenidos.

n. Los "elementos de la licencia" son las características principales de la licencia según la selección efectuada por el licen-ciador e indicadas en el título de esta licencia: Reconocimiento de autoría (Reconocimiento), Sin uso comercial (NoCo-mercial), Compartir de manera igual (CompartirIgual).

2. Límites y uso legítimo de los derechos. Nada en esta licencia pretende reducir o restringir cualesquiera límites legales delos derechos exclusivos del titular de los derechos de propiedad intelectual de acuerdo con la Ley de Propiedad Intelectual ocualesquiera otras leyes aplicables, ya sean derivados de usos legítimos, tales como el derecho de copia privada o el derecho acita, u otras limitaciones como la derivada de la primera venta de ejemplares.

3. Concesión de licencia. Conforme a los términos y a las condiciones de esta licencia, el licenciador concede (durante toda lavigencia de los derechos de propiedad intelectual) una licencia de ámbito mundial, sin derecho de remuneración, no exclusiva eindefinida que incluye la cesión de los siguientes derechos:

a. Derecho de reproducción, distribución y comunicación pública sobre la obra.

b. Derecho a incorporarla en una o más obras conjuntas o bases de datos y para su reproducción en tanto que incorporada adichas obras conjuntas o bases de datos.

c. Derecho para efectuar cualquier transformación sobre la obra y crear y reproducir obras derivadas.

d. Derecho de distribución y comunicación pública de copias o grabaciones de la obra, como incorporada a obras conjuntaso bases de datos.

e. Derecho de distribución y comunicación pública de copias o grabaciones de la obra, por medio de una obra derivada.

Page 196: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

196 / 198

Los anteriores derechos se pueden ejercitar en todos los medios y formatos, tangibles o intangibles, conocidos o por conocer.Los derechos mencionados incluyen el derecho a efectuar las modificaciones que sean precisas técnicamente para el ejerciciode los derechos en otros medios y formatos. Todos los derechos no cedidos expresamente por el licenciador quedan reservados,incluyendo, a título enunciativo pero no limitativo, los establecidos en la sección 4e.

4. Restricciones. La cesión de derechos que supone esta licencia se encuentra sujeta y limitada a las restricciones siguientes:

a. Usted puede reproducir, distribuir o comunicar públicamente la obra solamente bajo los términos de esta licencia y debeincluir una copia de la misma, o su Identificador Uniforme de Recurso (URI), con cada copia o grabación de la obra queusted reproduzca, distribuya o comunique públicamente. Usted no puede ofrecer o imponer ningún término sobre la obraque altere o restrinja los términos de esta licencia o el ejercicio de sus derechos por parte de los cesionarios de la misma.Usted no puede sublicenciar la obra. Usted debe mantener intactos todos los avisos que se refieran a esta licencia y a laausencia de garantías. Usted no puede reproducir, distribuir o comunicar públicamente la obra con medidas tecnológicasque controlen el acceso o uso de la obra de una manera contraria a los términos de esta licencia. Lo anterior se aplica auna obra en tanto que incorporada a una obra conjunta o base de datos, pero no implica que éstas, al margen de la obraobjeto de esta licencia, tengan que estar sujetas a los términos de la misma. Si usted crea una obra conjunta o base de datos,previa comunicación del licenciador, usted deberá quitar de la obra conjunta o base de datos cualquier referencia créditorequerido en el apartado 4d, según lo que se le requiera y en la medida de lo posible. Si usted crea una obra derivada, previacomunicación del licenciador, usted deberá quitar de la obra derivada cualquier crédito requerido en el apartado 4d, segúnlo que se le requiera y en la medida de lo posible.

b. Usted puede reproducir, distribuir o comunicar públicamente una obra derivada solamente bajo los términos de esta licen-cia, o de una versión posterior de esta licencia con sus mismos elementos principales, o de una licencia iCommons de Crea-tive Commons que contenga los mismos elementos principales que esta licencia (ejemplo: Reconocimiento-NoComercial-Compartir 2.5 Japón). Usted debe incluir una copia de la esta licencia o de la mencionada anteriormente, o bien su Identi-ficador Uniforme de Recurso (URI), con cada copia o grabación de la obra que usted reproduzca, distribuya o comuniquepúblicamente. Usted no puede ofrecer o imponer ningún término respecto de las obras derivadas o sus transformacionesque alteren o restrinjan los términos de esta licencia o el ejercicio de sus derechos por parte de los cesionarios de la misma.Usted debe mantener intactos todos los avisos que se refieran a esta licencia y a la ausencia de garantías. Usted no puedereproducir, distribuir o comunicar públicamente la obra derivada con medidas tecnológicas que controlen el acceso o usode la obra de una manera contraria a los términos de esta licencia. Lo anterior se aplica a una obra derivada en tanto queincorporada a una obra conjunta o base de datos, pero no implica que éstas, al margen de la obra objeto de esta licencia,tengan que estar sujetas a los términos de esta licencia.

c. Usted no puede ejercitar ninguno de los derechos cedidos en la sección 3 anterior de manera que pretenda principalmente ose encuentre dirigida hacia la obtención de un beneficio mercantil o la remuneración monetaria privada. El intercambio dela obra por otras obras protegidas por la propiedad intelectual mediante sistemas de compartir archivos no se considerarácomo una manera que pretenda principalmente o se encuentre dirigida hacia la obtención de un beneficio mercantil o laremuneración monetaria privada, siempre que no haya ningún pago de cualquier remuneración monetaria en relación conel intercambio de las obras protegidas.

d. Si usted reproduce, distribuye o comunica públicamente la obra o cualquier obra derivada, conjunta o base datos que laincorpore, usted debe mantener intactos todos los avisos sobre la propiedad intelectual de la obra y reconocer al autororiginal, de manera razonable conforme al medio o a los medios que usted esté utilizando, indicando el nombre (o el seu-dónimo, en su caso) del autor original si es facilitado, y/o reconocer a aquellas partes (por ejemplo: institución, publicación,revista) que el autor original y/o el licenciador designen para ser reconocidos en el aviso legal, las condiciones de uso, ode cualquier otra manera razonable; el título de la obra si es facilitado; de manera razonable, el Identificador Uniformede Recurso (URI), si existe, que el licenciador especifica para ser vinculado a la obra, a menos que tal URI no se refieraal aviso sobre propiedad intelectual o a la información sobre la licencia de la obra; y en el caso de una obra derivada, unaviso que identifique el uso de la obra en la obra derivada (e.g., "traducción castellana de la obra de Autor Original," o"guión basado en obra original de Autor Original"). Tal aviso se puede desarrollar de cualquier manera razonable; con talde que, sin embargo, en el caso de una obra derivada, conjunta o base datos, aparezca como mínimo este aviso allá dondeaparezcan los avisos correspondientes a otros autores y de forma comparable a los mismos.

e. Para evitar la duda, sin perjuicio de la preceptiva autorización del licenciador, y especialmente cuando la obra se trate deuna obra audiovisual, el licenciador se reserva el derecho exclusivo a percibir, tanto individualmente como mediante unaentidad de gestión de derechos, o varias, (por ejemplo: SGAE, Dama, VEGAP), los derechos de explotación de la obra,así como los derivados de obras derivadas, conjuntas o bases de datos, si dicha explotación pretende principalmente o seencuentra dirigida hacia la obtención de un beneficio mercantil o la remuneración monetaria privada.

Page 197: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

197 / 198

f. En el caso de la inclusión de la obra en alguna base de datos o recopilación, el propietario o el gestor de la base de datosdeberá renunciar a cualquier derecho relacionado con esta inclusión y concerniente a los usos de la obra una vez extraídade las bases de datos, ya sea de manera individual o conjuntamente con otros materiales.

5. Exoneración de responsabilidad

A MENOS QUE SE ACUERDE MUTUAMENTE ENTRE LAS PARTES, EL LICENCIADOR OFRECE LA OBRA TALCUAL (ON AN "AS-IS" BASIS) Y NO CONFIERE NINGUNA GARANTÍA DE CUALQUIER TIPO RESPECTO DE LAOBRA O DE LA PRESENCIA O AUSENCIA DE ERRORES QUE PUEDAN O NO SER DESCUBIERTOS. ALGUNASJURISDICCIONES NO PERMITEN LA EXCLUSIÓN DE TALES GARANTÍAS, POR LO QUE TAL EXCLUSIÓN PUEDENO SER DE APLICACIÓN A USTED.

6. Limitación de responsabilidad.

SALVO QUE LO DISPONGA EXPRESA E IMPERATIVAMENTE LA LEY APLICABLE, EN NINGÚN CASO EL LICEN-CIADOR SERÁ RESPONSABLE ANTE USTED POR CUALQUIER TEORÍA LEGAL DE CUALESQUIERA DAÑOS RE-SULTANTES, GENERALES O ESPECIALES (INCLUIDO EL DAÑO EMERGENTE Y EL LUCRO CESANTE), FORTUI-TOS O CAUSALES, DIRECTOS O INDIRECTOS, PRODUCIDOS EN CONEXIÓN CON ESTA LICENCIA O EL USO DELA OBRA, INCLUSO SI EL LICENCIADOR HUBIERA SIDO INFORMADO DE LA POSIBILIDAD DE TALES DAÑOS.

7. Finalización de la licencia

a. Esta licencia y la cesión de los derechos que contiene terminarán automáticamente en caso de cualquier incumplimiento delos términos de la misma. Las personas o entidades que hayan recibido obras derivadas, conjuntas o bases de datos de ustedbajo esta licencia, sin embargo, no verán sus licencias finalizadas, siempre que tales personas o entidades se mantengan enel cumplimiento íntegro de esta licencia. Las secciones 1, 2, 5, 6, 7 y 8 permanecerán vigentes pese a cualquier finalizaciónde esta licencia.

b. Conforme a las condiciones y términos anteriores, la cesión de derechos de esta licencia es perpetua (durante toda lavigencia de los derechos de propiedad intelectual aplicables a la obra). A pesar de lo anterior, el licenciador se reserva elderecho a divulgar o publicar la obra en condiciones distintas a las presentes, o de retirar la obra en cualquier momento.No obstante, ello no supondrá dar por concluida esta licencia (o cualquier otra licencia que haya sido concedida, o seanecesario ser concedida, bajo los términos de esta licencia), que continuará vigente y con efectos completos a no ser quehaya finalizado conforme a lo establecido anteriormente.

8. Miscelánea

a. Cada vez que usted explote de alguna forma la obra, o una obra conjunta o una base datos que la incorpore, el licenciadororiginal ofrece a los terceros y sucesivos licenciatarios la cesión de derechos sobre la obra en las mismas condiciones ytérminos que la licencia concedida a usted.

b. Cada vez que usted explote de alguna forma una obra derivada, el licenciador original ofrece a los terceros y sucesivoslicenciatarios la cesión de derechos sobre la obra original en las mismas condiciones y términos que la licencia concedidaa usted.

c. Si alguna disposición de esta licencia resulta inválida o inaplicable según la Ley vigente, ello no afectará la validez oaplicabilidad del resto de los términos de esta licencia y, sin ninguna acción adicional por cualquiera las partes de esteacuerdo, tal disposición se entenderá reformada en lo estrictamente necesario para hacer que tal disposición sea válida yejecutiva.

d. No se entenderá que existe renuncia respecto de algún término o disposición de esta licencia, ni que se consiente violaciónalguna de la misma, a menos que tal renuncia o consentimiento figure por escrito y lleve la firma de la parte que renuncieo consienta.

e. Esta licencia constituye el acuerdo pleno entre las partes con respecto a la obra objeto de la licencia. No caben interpreta-ciones, acuerdos o términos con respecto a la obra que no se encuentren expresamente especificados en la presente licencia.El licenciador no estará obligado por ninguna disposición complementaria que pueda aparecer en cualquier comunicaciónde usted. Esta licencia no se puede modificar sin el mutuo acuerdo por escrito entre el licenciador y usted.

Page 198: Programación en ensamblador de la arquitectura IA-32 ...ocw.uc3m.es/ingenieria-telematica/arquitectura-de-ordenadores/... · Programación en ensamblador de la arquitectura IA-32

Programación en ensamblador de laarquitectura IA-32

198 / 198

Creative Commons no es parte de esta licencia, y no ofrece ninguna garantía en relación con la obra. Creative Commons no seráresponsable frente a usted o a cualquier parte, por cualquier teoría legal de cualesquiera daños resultantes, incluyendo, pero nolimitado, daños generales o especiales (incluido el daño emergente y el lucro cesante), fortuitos o causales, en conexión con estalicencia. A pesar de las dos (2) oraciones anteriores, si Creative Commons se ha identificado expresamente como el licenciador,tendrá todos los derechos y obligaciones del licenciador.

Salvo para el propósito limitado de indicar al público que la obra está licenciada bajo la CCPL, ninguna parte utilizará lamarca registrada "Creative Commons" o cualquier marca registrada o insignia relacionada con "Creative Commons" sin suconsentimiento por escrito. Cualquier uso permitido se hará de conformidad con las pautas vigentes en cada momento sobre eluso de la marca registrada por "Creative Commons", en tanto que sean publicadas su sitio web (website) o sean proporcionadasa petición previa.

Puede contactar con Creative Commons en: http://creativecommons.org/.