Archivo de la categoría: Ensamblador

Programa informático que se encarga de traducir un fichero fuente escrito en un lenguaje ensamblador, a un fichero objeto que contiene código máquina, ejecutable directamente por el microprocesador

Ensamblador

Ensamblador

El lenguaje ensamblador es un lenguaje de bajo nivel cuyas instrucciones se suelen corresponder una a una con las instrucciones del ordenador, y con la posibilidad de poder definir, por ejemplo, macroinstrucciones

Este lenguaje es totalmente dependiente del modelo de procesador

Para poder estudiar este lenguaje con un microprocesador real se ha elegido el 8086, ya que es uno de los más utilizados en la actualidad en ordenadores de tipo PC

La principal característica de ese microprocesador es que es capaz de trabajar con operandos de 16 bits

Los ordenadores de tipo PC usan las operaciones básicas en 16 bits del 8086 y si el procesador es de 32 bits se le añaden un repertorio nuevo de operaciones en 32 bits. Si es de 64 bits entonces el repertorio de operaciones incluidas son de 16 bits, de 32 bits y un nuevo repertorio de 64 bits

Arquitectura básica del 8086

La arquitectura interna del 8086 se compone de dos partes diferenciadas: la Unidad de Ejecución y la Unidad de Interfaz con el bus

La tarea principal de la Unidad de Ejecución es ejecutar las instrucciones que extrae de la cola de espera, a donde llegan procedentes de la MP (Memoria Principal)

El trabajo principal de la Unidad de Interfaz con el bus es buscar y traer las instrucciones de la MP. Para ello tendrá que generar la dirección de la instrucción a ejecutar

Registros generales o de datos

Hay 4 registros de 16 bits y cada uno tiene una utilidad concreta:

  • AX
    Registro acumulador, se utiliza con las operaciones aritméticas
  • BX
    Registro de base, se utiliza para acceder a vectores, tablas, etc
    Mediante el uso de una dirección base que indica cual es el primer elemento y una dirección de desplazamiento que es el valor que se le suma a la dirección base para poder alcanzar el elemento deseado
  • CX
    Registro contador, se utiliza para contar en bucles e instrucciones de tipo repetitivo
  • DX
    Registro de datos, tiene dos usos particulares

    1. Complementar al registro AX en las operaciones aritméticas multiplicación y división
    2. Contiene direcciones de puerto para instrucciones de entrada / salida

Estos 4 registros tiene la siguiente propiedad común, aunque son de 16 bits, se pueden considerar cada uno de ellos como 2 registros independientes de 8 bits. De este modo podemos designar los bits más altos o significativos como Hight (al registro se le renombra con H al final: AH, BH, CH, DH) y los más bajos o menos significativos como Lower (al registro se le renombra con L al final: AL, BL, CL, DL)

Registros de segmento: Segmentación

Hay 4 registros de 16 bits y cada uno tiene una utilidad concreta:

  • CS
    Segmento de código, es el que define la zona de memoria donde se encuentran las instrucciones a ejecutar o de programa
  • DS
    Segmento de datos, es el que define la zona donde se encuentran los datos que van a ser usados en el programa
  • SS
    Segmento de stack o pila, define la zona de memoria que se va a utilizar como una pila
  • ES
    Segmento extra, como su nombre indica contiene la dirección del segmento extra, que se utiliza cuando se sobrepasa la capacidad de 64 kbytes del segmento de datos y para realizar determinadas transferencias de datos entre segmentos

Bus de datos: lineas por las que se transmiten los datos

Anchura del bus de datos: número de lineas eléctricas del bus por las que se transmiten los datos, en el 8086 son de 16 bits

Bus de direcciones: lineas por las que se transmiten las direcciones

Anchura del bus de direcciones: número de lineas eléctricas del bus por las que se transmiten las direcciones, en el 8086 son de 16 bits

Por tanto, las direcciones deberían ser de 16 bits, sin embargo, en el 8086 son de 20 bits. Esto es debido a que el número de direcciones distintas sería 2^{16}=64K, pero como son muy pocas, nos interesa que sean de 20 bits, ya que 2^{10}=1M

Para calcular la dirección física necesitamos un segmento y un desplazamiento, usando siempre valores en hexadecimal, con lo que tendremos un primer registro de 16 bits al que se añadirá un 0 a su derecha y un segundo registro de 16 bits

Como notación se usa Segmento:Desplazamiento

El cálculo de la dirección física se realizará:
Segmento x 10(h) + Desplazamiento

Ejemplos de Segmento:Desplazamiento

  • 0000:1050\Rightarrow 0000\cdot 10+1050=0150
  • 0010:0F50\Rightarrow 0010\cdot 10+0F50=0150
  • 0100:0050\Rightarrow 0100\cdot 10+0050=0150
  • 0105:0000\Rightarrow 0105\cdot 10+0000=0150

Como puede apreciarse en los ejemplos, distintas combinaciones de segmentos y desplazamientos pueden darnos la misma dirección física. Esta situación no es un error, es debido a que las direcciones de los segmentos se solapan entre sí

Podemos tener tantos números de segmentos distintos como combinaciones distintas puedan hacerse con la dirección base de segmento. Como tiene 16 bits entonces tenemos 2^{16} combinaciones por lo que tenemos 64\cdot K direcciones distintas

Podemos tener tantos números de direcciones distintas en cada segmento como combinaciones distintas puedan hacerse con el desplazamiento. Como tiene 16 bits entonces tenemos 2^{16} combinaciones por lo que tenemos 64\cdot K direcciones distintas

Se podría pensar que como tenemos 64\cdot K segmentos y 64\cdot K direcciones, tendríamos 64\cdot 64=2G direcciones físicas. Sin embargo, como las direcciones están solapadas este número de direcciones es incorrecto

Las direcciones válidas de comienzo de segmento tienen la propiedad de acabar en 0. Por tanto, ya que en hexadecimal son 10, al pasar de hexadecimal a decimal obtenemos que el número de direcciones es 16