Capítulo 1. Introducción

Tabla de contenidos

1.1. Perspectivas de un ordenador
1.2. Niveles de abstracción
1.2.1. Estudio de un procesador a nivel lenguaje máquina
1.3. Estructura de un ordenador
1.4. Definición de un programa
1.5. El lenguaje ensamblador
1.5.1. Programación en lenguaje ensamblador
1.5.2. Ejecución de un programa en ensamblador
1.6. Ejecución de un programa
1.7. Ejercicios
Bibliografía

En este capítulo se describen las diferentes formas posibles de percibir un ordenador y su funcionamiento. El usuario común lo percibe como una máquina capaz de ejecutar ciertas órdenes o comandos que se le comunican utilizando los dispositivos tales como teclado, ratón, etc. Pero para la persona con nociones básicas de electrónica digital, el ordenador es un circuito complejo que permite 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 usuario convencional introduce un comando por teclado, el ordenador lo ejecuta mediante un número muy elevado de instrucciones básicas que permiten la comunicación con los diferentes dispositivos para obtener los datos así como las operaciones básicas en el interior del procesador. Se verá cómo tareas comunes solicitadas por un usuario requieren la participación de varias partes del ordenador.

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 frente a uno de ellos y comienza a trabajar, el ordenador se percibe como un objeto que permite manipular una serie de programas que a su vez realizan una serie de tareas. Por ejemplo, al conectarse a Internet y entrar en un chat, el ordenador permite, a través del programa de chat, el intercambio de mensajes con un conjunto de personas que a su vez están utilizando ese mismo programa en otros ordenadores en otros lugares. Pero además de utilizar el programa de chat, no se debe olvidar que se se está utilizando igualmente la pantalla para visualizar los mensajes, el teclado para introducir su texto, y posiblemente el ratón para seleccionar iconos 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. El ordenador facilita el trabajo de escritura y almacenamiento de este documento que puede incluir elementos especiales tales como imágenes, diferentes tipos de letras, gráficas con datos, etc. Para realizar esta tarea también se utiliza la pantalla para visualizar los datos, el teclado para introducir texto, y el ratón para realizar tareas de selección y manipulación de texto. Si este documento creado de forma electrónica se necesita en papel, el ordenador permite enviarlo a una impresora que se encarga de plasmar en papel 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 previamente introducidas o programadas en el ordenador y por tanto puede ejecutarlas cuando el usuario así lo requiera. Pero los ordenadores poseen una propiedad que los hace realmente potentes: se pueden programar con tareas nuevas. Es decir, si un ordenador no dispone del programa necesario para realizar una tarea, y ésta es programable, existen lenguajes de programación tales como Java que permiten escribir estos programas e instalarlos. A partir de ese momento, el ordenador podrá ejecutar el programa escrito 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, no son los que el ordenador entiende directamente. Antes de instalar un programa es preciso traducirlo al lenguaje básico que se maneja internamente. A este proceso de traducción se le denomina compilación. Según el diccionario de la lengua española, la palabra compilar significa “preparar un programa en el lenguaje máquina a partir de otro programa de ordenador escrito en otro lenguaje”. Una vez que el programa ha sido traducido o compilado, el ordenador ya puede ejecutarlo. Esta forma de utilizar un ordenador, como un objeto al que podemos darle órdenes precisas sobre tareas, mediante un programa escrito en un lenguaje de programación, y que se traduce al lenguaje máquina interno del ordenador, es lo que denominaremos la “perspectiva del programador”. La figura 1.1 muestra de forma gráfica los elementos de la perspectiva del programador.

Figura 1.1. Perspectiva del programador

Perspectiva del programador

Pero además de los ejemplos cotidianos de uso, es posible percibir un ordenador desde una perspectiva totalmente diferente. En efecto, si se dispone de nociones básicas de electrónica digital, se sabe que en su interior hay una serie de circuitos electrónicos interconectados entre sí. Si se abre la caja de un ordenador puede verse todo un conjunto de pequeños circuitos interconectados por infinidad de cables que atraviesan una superficie rígida conocido genéricamente con el nombre de “placa”. Los circuitos, a su vez están diseñados utilizando puertas lógicas, que a su vez constan de un conjunto de transistores. La manera en que dichas puertas 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 por otro 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 discos duros suelen tener aspecto de caja metálica rectangular con conectores en uno de sus lados. Puede verse cómo algunos de los conectores que aparecen en la parte posterior de la caja del ordenador están conectados a pequeñas placas con circuitos impresos que 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 de los ordenadores, porque es el circuito de mayor tamaño en el equipo y requiere su propio ventilador para evitar recalentamientos por lo que no suele estar directamente visible. Este circuito es el que se conoce con el nombre de procesador, y es el responsable de dirigir, controlar y ejecutar las principales tareas que realiza el ordenador. La característica fundamental de este procesador es que puede ejecutar programas en lenguaje máquina. Por tanto, el lenguaje máquina es aquél que consta de las instrucciones o comandos 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 capacidad se debe a la presencia del procesador. Esta perspectiva del ordenador como un conjunto de circuitos electrónicos interconectados entre sí se denominará la perspectiva del diseñador. La figura 1.2 muestra algunos de los elementos de los que consta esta perspectiva.

Figura 1.2. Perspectiva del diseñador

Perspectiva del diseñador

Una vez vistas estas dos perspectivas posibles, ¿cómo puede un equipo formado por estos componentes electrónicos permitirnos tareas 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 de este documento se ofrece parte de la respuesta a dicha pregunta mediante la explicación del funcionamiento de un procesador desde el punto de vista de su programación en lenguaje máquina. La programación en lenguajes como Java es posible porque los programas 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 de usuario. El estudio del ordenador se centra alrededor del procesador y su lenguaje máquina, que es capaz de ofrecer la funcionalidad necesaria para ejecutar los programas diseñados en lenguajes tales como Java. La figura 1.3 ilustra la nueva perspectiva a estudiar con respecto a las dos anteriores.

Figura 1.3. Diferentes perspectivas de un ordenador

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 permitan simplificarlo pero que a la vez se muestren sus aspectos más relevantes. A este proceso de simplificación, en el que ciertos aspectos 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 del mundo mediante su dirección de correo postal. Las direcciones de correo postal incluyen el país en el que se encuentra el destinatario. 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ís especificado en la dirección. En una segunda fase, se obtiene la información sobre la división interna de un país (estas divisiones pueden tener diferentes nombres tales como comunidades, provincias, departamentos, estados, etc.) Una vez localizada la unidad territorial se debe seleccionar una ciudad. Para ello, tan sólo es preciso obtener la información de ciudades incluidas en la unidad territorial bajo consideración y localizar la del destinatario. Finalmente, dentro de la ciudad se debe obtener la información sobre las 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:

  • 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 información sobre todos los países del mundo puede incluir además todas las divisiones en unidades territoriales. De igual forma, los datos sobre todas las ciudades de una unidad territorial puede incluir todas sus calles. Sin embargo, la solución del problema de localizar un edificio se simplifica sustancialmente si los datos están divididos en las categorías antes mencionadas, es decir, una categorí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ón acerca de la localización de edificios en el mundo pero, a la vez, conservando los aspectos más relevantes. Cada una de estas categorí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 forma que cada una de ellas provee más detalle que el nivel anterior, pero ignora detalles del nivel siguiente. Como conclusión, entre los niveles de abstracción se puede establecer una relación con respecto a dos aspectos: la complejidad y el detalle. La figura 1.4 ilustra un ejemplo con cuatro niveles y cómo la complejidad y el detalle se relacionan de manera inversa. A mayor nivel de complejidad, 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

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ón de algunos de los aspectos contenidos en una determinada área. El tamaño del mapa y el de dicha área están relacionados mediante un factor de escala. Es posible tener mapas de la misma área pero realizados a diferente factor de escala. Estos mapas ofrecen 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 la realidad mediante un nivel de abstracción adecuado. Por ejemplo, si una empresa de distribución de mercancías a nivel mundial necesita decidir dónde situar sus centros de distribución, no es preciso que utilice la información de qué números hay en cada calle. Igualmente, un ingeniero que desea diseñar una autopista no puede utilizar un mapa con una escala tan grande que no se perciban 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 uno de ellos contiene diferentes tipos de detalles. A nivel más detallado, un procesador funciona como un circuito electrónico en el que 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 y la comunicación a través de sus dispositivos.

De entre estos dos niveles de abstracción, el estudio que se presenta en este documento está realizado a nivel del lenguaje máquina que el procesador es capaz de ejecutar. Para clarificar más los detalles que forman parte de este nivel los compararemos con los niveles 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 instrucciones que se escriben son más sofisticadas (bucles, condicionales, comparaciones, etc) y se ciñen a una sintaxis específica de dicho lenguaje. Nótese que un mismo procesador puede ejecutar programas escritos en diferentes lenguajes de programación. Tan sólo es 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 con el 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 detalles son imprescindibles para entender cómo se ejecutan paso a paso las diferentes instrucciones que forman parte del lenguaje máquina. Basándose en la estructura interna de un procesador se puede entender, por ejemplo, el tiempo que tarda éste en ejecutar una determinada instrucción así como los circuitos que utiliza. Análogamente al nivel de abstracción anterior, en los siguientes capítulos se mencionarán algunos detalles de este nivel para facilitar la comprensión de cómo el procesador ejecuta las 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 que esté orientado el equipo. Así, un ordenador de los denominados “personales”, es decir, orientado a realizar tareas relativas a una persona, puede tener una estructura diferente a un ordenador que utilizado para el almacenaje masivo y acceso al conjunto de datos 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 optado por presentar un modelo simplificado de la arquitectura de un ordenador personal, también conocido como PC que es la abreviatura del término inglés personal computer. La figura 1.5 ilustra este modelo.

Figura 1.5. Estructura de un ordenador

Estructura de un ordenador

Todo ordenador tiene, como parte fundamental de su arquitectura, al menos un procesador. En su interior se encuentran una serie de elementos básicos tales como registros (capaces de almacenar pequeñas cantidades de información), unidad aritmético-lógica o UAL (capaz de realizar simples operaciones aritméticas), unidad de control, etc. Este procesador se comunica con el resto del ordenador 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 circuito representado 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 con la memoria RAM se realiza a través del bus de memoria. Esta memoria es capaz de almacenar información mientras el equipo esté encendido. Al apagar el equipo, los datos almacenados en este dispositivo se pierden, por este motivo, también se le conoce como 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 se utiliza para conectar todos los dispositivos auxiliares que necesita el ordenador para su funcionamiento. Dichos dispositivos no se 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 el disco duro. Teclado y ratón son dos dispositivos de entrada de datos (el ordenador sólo recibe datos de ellos), la pantalla es de salida de datos, y el disco duro es de entrada y salida de datos (se realizan operaciones de lectura y escritura). Este disco tiene una funcionalidad similar a la memoria RAM, es decir, almacenar datos, pero con la diferencia de que si se apaga el equipo, la información permanece almacenada sin alteraciones. A los dispositivos con esta propiedad (disco duro, CD-ROM, DVD, etc.) se les 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 la posibilidad de conectar de forma sencilla dispositivos adicionales. El bus de entrada/salida está preparado para conectar más dispositivos y así dotar al ordenador de mayor capacidad. De esta forma, el ordenador se puede completar con una impresora, un scanner, discos duros adicionales, lector/grabador de DVDs, etc. La mayoría de estos dispositivos se conectan al ordenador ya 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án escritos 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 pueden apreciar detalles comunes a cualquier programa.

Ejemplo 1.1. Programa en Java

// Definición de la clase Programa
public class Programa {
    // Definición del método main
    public static void main(String[] args) {
        String mensaje;
        
        // Inicialización del mensaje a imprimir
        mensaje = new String("Este es mi primer programa");

        // Imprimir el mensaje
        System.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 estipuladas por la definición del lenguaje de programación Java. Todo programa define un conjunto de órdenes a ejecutar sobre un conjunto de 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 ejemplo es 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 el caso concreto de Java, este fichero ha de contener lo que se denomina texto plano, es decir, un fichero que contenga únicamente el texto 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 al lenguaje que el procesador es capaz de entender, es decir, a lenguaje máquina. En general, este proceso de traducción consiste en varios pasos o etapas que son realizadas por varios programas diferentes. Existen lenguajes de programación y ordenadores en el 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últiples pasos y cada uno de ellos lo realiza un programa diferente. En el ejemplo del programa Java, el proceso de traducción a lenguaje máquina se ilustra en la figura 1.6.

Figura 1.6. Creación de un ejecutable en Java

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 al usuario. 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 fichero fuente produce un fichero temporal con extensión .class. A partir de este fichero, la herramienta java realiza la traducción que falta 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ón de ceros y unos. En otras palabras, todas las instrucciones que es capaz de ejecutar un procesador se deben codificar mediante ceros y unos de una forma específica e inequívoca. Se puede decir, por tanto, que el lenguaje del procesador es el lenguaje má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 unos codificando los datos y las órdenes del programa. Para facilitar esta tarea se define el lenguaje ensamblador que no es más que una 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 en ceros y unos del programa para su posterior ejecución. Dada la proximidad entre estos dos lenguajes, a menudo sus nombres se utilizan de manera indistinta.

El ejemplo 1.2 muestra un sencillo programa escrito en lenguaje ensamblador del procesador Intel Pentium®. En los siguientes capítulos se hace un estudio más detallado del lenguaje máquina de este procesador así como de sus principales características. Por el momento, es suficiente saber que el código máquina mostrado corresponde a dicho procesador. De la mera inspección visual de este programa se pueden deducir varios aspectos de la programación en lenguaje ensamblador.

Ejemplo 1.2. Programa en ensamblador

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

        .text                                 # Comienza la sección de código
        .globl main                           # Declaración de main como símbolo 
				              # global
main:   
        push %ebp                             # Bloque de activación
        mov  %esp, %ebp

        push $mensaje                         # mueve un dato a la pila

        call printf                           # printf es una función que
                                              # imprime por pantalla los
                                              # datos que recibe

        add $4, %esp                          # borra la cima de la pila

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

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

La segunda sección comienza a partir de la palabra .text como indica el comentario en la misma línea. A continuación encontramos una línea en la que el símbolo main se define como global (sin saber qué quiere decir esto). Lo más revelador del programa se encuentra a partir de este punto, pues aparece la palabra main seguida por cuatro líneas que se corresponden con cuatro 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 es el caso de la última línea) o de una palabra seguida de una o dos más separadas por comas. Estas instrucciones pueden incluir palabras 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 programa imprime 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 programas en común es que contienen un conjunto de órdenes y los datos utilizados. Aunque en estos dos ejemplo no es aparente, el nivel de abstracción que ofrecen estos dos lenguajes con respecto al lenguaje máquina es muy diferente. Mientras el lenguaje ensamblador es prácticamente idéntico al lenguaje máquina, el lenguaje Java, por el contrario, ofrece construcciones que se aproximan a construcciones complejas orientadas a ser entendidas por un humano. A este tipo de lenguajes se les denomina lenguajes de alto nivel. Como consecuencia, el proceso de traducción y producción de un ejecutable es mucho más fácil para el programa 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 son luego traducidas a lenguaje máquina y ejecutadas por el procesador. Por otro lado, el lenguaje ensamblador no es más que una representación textual del lenguaje máquina. ¿Qué ventaja tiene escribir un programa en lenguaje ensamblador pudiendo utilizar un 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ón de estos lenguajes viene motivada, en parte, para evitar programas en lenguaje ensamblador pues suelen ser muy delicados de construir. Pero a pesar de ello, la programación en ensamblador sigue vigente en nuestros días. Sus ventajas son múltiples tal y como 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 la comprensió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 eficientes 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 el procesador, se requiere un proceso de traducción o compilación. Este proceso consta de varios pasos que pueden ser realizados por 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 para la ejecución de programas. La forma habitual de utilizar este programa es mediante una ventana en la que el intérprete muestra un mensaje denominado prompt y espera a que el usuario teclee la orden a ejecutar. Una vez introducido un comando, el intérprete lo ejecuta, y al terminar ofrece de nuevo el prompt y espera el siguiente comando. En adelante se utilizará el símbolo $ para representar 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 programa escrito en lenguaje ensamblador. La compilación la realiza el programa gcc a la que se le proporciona una opción para que el ejecutable se almacene en un fichero con nombre programa (texto -o programa). La ejecución de esta herramienta realiza los 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

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

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 partir de lenguaje ensamblador. La funcionalidad de esta herramienta se controla mediante opciones que se añaden a continuación de su 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 ensamblado y 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 prompt y 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:

$ programa
Este es mi primer programa
$

Cuando el usuario introduce el nombre del fichero ejecutable programa, el procesador está ejecutando el intérprete de comandos. Cuando el usuario pulsa las teclas para escribir la palabra programa el teclado notifica al procesador de que se ha pulsado una tecla, y este obtiene la letra del controlador y la muestra por pantalla. Este proceso se repite para cada una de las letras mientras 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

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 la almacena en memoria. Pero el retorno de carro es la marca de final de comando que hace que el intérprete de comandos pase 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. A continuació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

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 un programa en memoria principal en donde puede acceder a ellos directamente mediante instrucciones de su lenguaje máquina. El acceso al disco duro, por el contrario, requiere la ejecución de múltiples instrucciones máquina para calcular el lugar del disco en el que se encuentran los datos solicitados y para programar el controlador de disco para que obtenga dichos datos y los deposite en 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 del programa tal y como se muestra en la figura 1.10 que es push $mensaje. A partir de ese instante el procesador está ejecutando las instrucciones escritas en el programa sobre los datos definidos.

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

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 su vez está diseñado para que cuando se termina la ejecución de un programa se vuelva a mostrar el prompt (el símbolo $) por pantalla. 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 proceso de 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 un humano?

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

  7. A la vista de las operaciones que realiza el procesador para ejecutar un proceso cuyo nombre introduce el usuario a través de teclado, idear y describir una tarea en la que el ordenador tenga que procesar información obtenida a través de las clavijas 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 entre sí. ¿Puede un fichero ejecutable de un procesador ser ejecutado en general en otro procesador con un lenguaje máquina diferente? Justificar la respuesta.

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

Envío de errata

Bibliografía

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