Está en la página 1de 15

Unidad 2 / Escenario 4

Lectura fundamental

Diseño de un lenguaje ensamblador

Contenido

1 Caso de estudio

2 Especificaciones de diseño

3 Diseño del conjunto de instrucciones

4 Diseño de algoritmos en bajo nivel

Palabras clave: set de instrucciones (ISA), lenguaje ensamblador, procesador


A través de esta lectura se cubrirá toda la etapa de diseño de un conjunto (set) de instrucciones,
que hace parte a su vez del diseño de un procesador, para el ejemplo, de propósito específico. Este
“propósito específico” se determinó como un ejemplo para abordar un problema que se desea
solucionar con el procesador que se está desarrollando; en términos prácticos: diseñar hardware capaz
de ejecutar una tarea o algoritmo específico. En esta lectura, se conocerá el proceso de programar
hardware, el nivel más bajo de abstracción para programar, a través de una secuencia práctica que se
basa en lo presentado en la lectura anterior.

A continuación, se presenta el caso de estudio: procesador de propósito específico cuyo objetivo es


determinar la suma de los n primeros números enteros.

1. Caso de estudio

1.1. Planteamiento del problema

Se requiere diseñar un procesador que permita dar solución al siguiente problema: “Encontrar el valor
de los n primeros números, donde n se encuentra almacenado en una variable". El paso a paso del
diseño de la solución se abordará teniendo como lineamiento guía el problema mencionado.

1.2. Aproximación a la solución

Luego de tener claro y delimitado el problema que se desea resolver, el siguiente paso es generar
el algoritmo solución, que no es más que una serie de pasos ordenados y finitos cuya ejecución
solucionará la problemática planteada. Inicialmente, este algoritmo se genera en lenguaje natural,
para que su entendimiento sea sencillo: “Realizar un ciclo en el que se va a ir acumulando la suma de
todos los números, de uno en uno, hasta llegar al número n”.

Una vez generado el algoritmo es importante revisarlo y verificar que efectivamente solucione todos
los escenarios posibles delimitados por el problema que se busca solucionar. Un error en el alcance o
las restricciones, pueden generar un diseño de procesador completamente diferente, con la pérdida
de tiempo que tal situación conlleva.

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 2
1.3. Algoritmo

Finalmente, es necesario convertir el algoritmo anterior a un lenguaje de programación de alto nivel,


no importa que lenguaje se use, lo importante es mantener un enfoque simple y estructurado para el
código. La claridad en la estructura del código ayudará a reconocer las instrucciones necesarias en el
conjunto de instrucciones.

int suma=1;
int n=10;
for (int numero=2; numero<=n; numero=numero+1) {

2. Especificaciones de diseño
Antes de comenzar la construcción del conjunto de instrucciones que se va a implementar en el
procesador, se deben tener claras algunas consideraciones que pueden impactar fuertemente su
proceso de diseño, tales como: ¿Cuántas instrucciones se podrán soportar? ¿Qué datos manejará
el procesador? ¿Qué tan largo puede ser el programa a ejecutar? ¿Cuántas variables auxiliares o
temporales se podrían manejar? ¿Cuáles son las estructuras, procesos u operaciones más complejas
que se podrían necesitar? Dado que para nuestro caso de estudio contemplamos un procesador
de propósito específico, estas consideraciones se reducen al algoritmo solución, pero si el que
estuviéramos construyendo fuera un procesador de propósito general, como el de los computadores
personales, todas estas cuestiones adquieren un nivel de trascendencia mucho más alto.

¡Recuerde!..
Las especificaciones del diseño de un conjunto de instrucciones
impactarán en la micro arquitectura del procesador, que veremos en la
siguiente unidad, de ahí la importancia de reflexionar sobre el alcance y las
restricciones que tendremos en cuenta durante el proceso de diseño.

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 3
2.1. Tamaño de los datos

A partir del algoritmo en alto nivel generado previamente, se debe identificar qué tipos de datos son
imprescindibles para la ejecución del mismo, pues entre menos complejos sean estos, probablemente
se necesitará menos memoria y una microarquitectura más sencilla para manejarlos. En ese orden
de ideas, en la siguiente tabla, se presenta un comparativo entre tipos de datos de alto nivel y su
equivalencia en bajo nivel.

Tabla 1. Tipos de datos

Tipo de dato Alto nivel Bajo nivel (ensamblador) Valor que puede representar

Números enteros desde


Registro o bloque de memoria
Natural BYTE 0 hasta 255 (No incluye
de 8 bits
números con signo)
Números enteros desde -128
Entero Registro o bloque de memoria
BYTE hasta 127 (Incluye números
(pequeño) de 8 bits
con signo)
Números enteros desde -231
Entero Registro o bloque de memoria
INT hasta 231- 1 (Incluye números
(largo) de 32 bits
con signo)

Números decimales desde


Real Registro o bloque de memoria ±3,4·10-38 hasta ±3,4·1038
FLOAT
(pequeño) de 32 bits (Incluye números con signo y
decimales)

Números decimales desde


Registro o bloque de memoria ±1,7·10-308 hasta ±1,7·10308
Real (largo) DOUBLE
de 64 bits (Incluye números con signo y
decimales)

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 4
Todos los caracteres
alfanuméricos definidos en
Cadena de Registro o bloque de memoria
CHAR ASCII, incluyendo signos
caracteres de 8 bits por cada letra
de puntación, acentos y
caracteres especiales

Registro o bloque de memoria


de 1 bit (usualmente se
Dos estados: True (1) o False
Booleano BOOLEAN agrupan varios booleanos en
(0)
un solo registro o bloque de
memoria)

Fuente: elaboración propia

Como se observa, según el tipo de dato y su longitud se puede requerir o una cantidad alta de
registros en nuestro procesador, o registros de una longitud muy grande (32 bits, 64 bits o más).
Dimensionar la solución que se ve a proponer es clave para delimitar correctamente el alcance del
procesador. Para nuestro caso de estudio, donde se busca un diseño simple que permita practicar
los conceptos presentados fácilmente, se identifican sólo variables numéricas. Adicionalmente, por
simplicidad, se determinó que estos números fueran enteros pequeños. Así, se tendrán registros de
8 bits que serán suficientes para cubrir el objetivo pedagógico del procesador del caso de estudio. A
continuación observamos las variables identificadas.

Escribirlo en fuente de código y resaltado.

int suma=1;
int n=10;
for(int numero=2; numero<=n; numero=numero+1) {
suma=suma+numero;
}

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 5
2.2. Registros: cantidad y funcionalidad

En un procesador existen 2 grandes tipos de registros:

• Los registros visibles por el usuario

• Los registros de control y de estado

La gran diferencia entre estos es que los registros visibles por el usuario son también manipulables
por el mismo, convirtiéndose en variables auxiliares o temporales para la ejecución de algoritmos en
el procesador, minimizando así las referencias a la memoria principal y haciendo los programas más
óptimos en su ejecución. Mientras que los registros de control y estado, no pueden ser manipulados
directamente, lo que quiere decir que en ellos no se pueden guardar valores temporales, la única
manera de que cambien es debido a un cambio de estado monitorizado en el procesador.

Normalmente se encuentran entre 2 a 64 registros visibles por el usuario en un procesador, y suelen


ser de uso general, para guardar datos, direcciones de memoria y códigos de condición. Para nuestro
caso de estudio, se ha mostrado que solo usaremos 3 variables auxiliares, por lo que al definir 8
registros de este tipo es suficiente. Es importante tener en cuenta que entre más registros se definan,
más bits de control se requieren para su direccionamiento y por lo tanto más complejidad adquiere
la microarquitectura del mismo, para nuestro caso requeriremos 3 bits para direccionarlos (23 = 8
registros) y 1 bit para definir si vamos a leer o a escribir el registro seleccionado.

Hay diversos registros del procesador que se emplean para controlar su funcionamiento. La mayoría
de ellos no son visibles por el usuario y se clasifican como registros de control y de estado.

Naturalmente, procesadores diferentes tendrán distintas organizaciones de registros y usarán distinta


terminología. A continuación, se presenta una lista de posibles registros de control para la ejecución
de una instrucción, con una breve descripción:

• Contador de programa (PC): Contiene la dirección de la instrucción a captar y posteriormente a


ejecutar.

• Registro de instrucción (IR): Contiene la última instrucción captada.

• Registro de dirección de memoria (MAR): Contiene la dirección de una posición de la memoria


principal.

• Registro intermedio de memoria (MBR): Contiene la palabra de datos a escribir en la memoria


principal o la palabra leída más reciente.

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 6
• Registro de estado (SR): Contiene un conjunto de “banderas”, representadas cada una por un
bit (1 o 0) que indican el estado actual del procesador. (Stallings, 2005)

El conjunto de registros depende de la arquitectura que se proponga o que se estudie. Sin embargo,
algunos como el PC, son esenciales en todas las arquitecturas modernas.

3. Diseño del conjunto de instrucciones


Luego de haber estudiado los datos y variables que se necesitan, es el turno de revisar las operaciones
o instrucciones que nuestro procesador debe realizar.

El primer paso es identificar de la manera más detallada posible las instrucciones a partir del algoritmo
en alto nivel. Especificando por ejemplo qué tipo de dato maneja la instrucción, de dónde se obtienen
los operandos que utiliza la instrucción y dónde será almacenado el resultado de la misma.

3.1. Tipos de instrucción

De acuerdo con la selección realizada anteriormente, existen tres tipos de instrucciones a diseñar,
que se estudiarán a continuación.
3.1.1. Instrucciones aritméticas:

Aquellas que realizan operaciones aritméticas entre uno o más números (operandos). Entre estas
operaciones se encuentran: suma, resta, multiplicación, división, potenciación, logaritmación,
radicación, etc. Es importante recordar que todas las operaciones aritméticas en sistema binario pueden
ser expresadas como sucesiones de sumas, por lo anterior se debe cuestionar si vale la pena crear
instrucciones para cada una de las operaciones matemáticas que puedan existir, con el consecuente
aumento en la complejidad del montaje del hardware del procesador, o si para el propósito buscado basta
con tener solo la suma, o solo las 4 operaciones básicas.

¡Recuerde!...
Puedes diseñar diversas instrucciones para implementar operaciones
distintas a nivel de hardware, o puedes tener instrucciones básicas, a partir
de las cuales se puedan crear operaciones más complejas por software.

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 7
3.1.2. Instrucciones lógicas:

Aquellas que, como su nombre lo indica, ejecutan operaciones lógicas bit a bit con sus operandos,
tales como NOT, AND y OR, y sus combinaciones NAND, NOR, XOR, XNOR, etc. Es importante
reflexionar si el procesador que se diseña necesita operaciones lógicas y si las necesita todas, ya
que esto redunda también en la cantidad de instrucciones del conjunto de instrucciones y en la
complejidad de la ALU (Unidad Lógico Aritmética) del procesador, que se presentará en la siguiente
unidad del módulo.

3.1.3. Instrucciones de control:

Son todas aquellas instrucciones que alteran la ejecución vertical (en caída libre) del código del
algoritmo a ejecutar, aquí se incluyen los saltos condicionales (por mayor que, menor que, igual,
menor o igual, mayor o igual, etc.) y los saltos incondicionales. Es importante recordar que los
programas en lenguaje ensamblador normalmente se ejecutan siempre de manera secuencial (una
línea de código justo después de haber terminado de ejecutar la línea anterior), siempre y cuando no
aparezca una instrucción de salto, que puede hacer que la siguiente línea que se ejecute sea la primera
o la última del programa, o en general, cualquier línea que se señalice con la etiqueta que acompaña
la instrucción de salto. Su funcionamiento es similar al GOTO que poseen algunos lenguajes de
programación de alto nivel, aunque en estos se recomienda evitar su uso. Sin embargo, en el bajo nivel
es la forma en que se ejecutan ciclos (volver a ejecutar el código desde determinada línea) y bloques
condicionales (ejecutar determinada línea de código si la operación anterior se cumple (true) y no
(false)).

En la Tabla 2 se presenta el conjunto de instrucciones diseñado para el problema ejemplo particular,


incluyendo el nombre de la instrucción, su código, tipo, ejemplo y significado.

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 8
Tabla 2. Conjunto de instrucciones diseñado para resolver el problema de calcular
la suma de los primeros números naturales.

Significado
Instrucción Cód Operandos Ejemplo Significado
matemático

Asigna a r1 el valor de 10
cargar 00 reg,valor cargar r1,10 r1=10
(en decimal)

reg1, reg2, brMayor r1, if(r1>r2) Si r1 es mayor que r2, salta a


brMayor 10
etiqueta r2, lugar goto lugar la línea con etiqueta “lugar”

reg1, reg2, sumar r3, Guarda en r3 el resultado


sumar 01 r3=r2+r1
etiqueta r1, r2 de sumar r1 con r2.

Salta a la línea de
saltar 11 etiqueta saltar lugarS saltar lugarS lugarS sin depender de
ninguna condición

Fuente: elaboración propia

3.2. Formatos de instrucción

Un formato de instrucciones define la descripción en bits de una instrucción, en términos de las


distintas partes o campos que la componen. Un formato de instrucciones debe incluir un código de
operación (codop), e implícita o explícitamente, cero o más operandos. Cada operando se referencia
según uno de los modos de direccionamiento vistos previamente en el curso. El formato debe,
implícita o explícitamente, indicar el modo de direccionamiento de cada operando. En la mayoría de
los repertorios de instrucciones se emplea más de un formato de instrucción (Stallings, 2005).

Como se puede dimensionar, definir el formato de instrucción no es una tarea trivial, deben tenerse
en cuenta aspectos fundamentales como:

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 9
3.2.1. Longitud de la instrucción:

En este ítem se debe definir si la instrucción tendrá longitud fija o variable. Como es de esperarse,
manejar una longitud fija permitirá definir fácilmente el tamaño de los bloques de la memoria de
programa donde se almacenarán los algoritmos, disminuyendo complejidad en la construcción del
procesador. Esta longitud dependerá de la cantidad de instrucciones a implementar, del máximo de
operandos que pueden soportar las instrucciones y de los modos de direccionamiento que utilice cada
una. La cantidad total de instrucciones definirá el número de bits, n, que utilizará la identificación
única de cada instrucción, también conocida como código de operación (codop), tal que 2n = Total
de instrucciones. Se debe tener en cuenta que si se diseña una misma operación que utiliza distintos
modos de direccionamiento, o diferente cantidad de operandos, cada una de estas variantes se cuenta
como una instrucción diferente, por lo que requerirá un codop diferente. Por último, es evidente
que si definimos instrucciones que puedan manejar 4 operandos, éstas serán necesariamente más
largas que si solo definimos una que manejen 3 operandos. Por lo anterior, se suele buscar un punto
de equilibrio donde el programador del procesador tenga suficiente flexibilidad, pero sin tener que
diseñar instrucciones demasiado largas que terminen ocupando más espacio en memoria y haciendo
la microarquitectura del procesador más compleja.

3.2.2. Asignación de los bits:

Luego de tener las operaciones identificadas y de haber decidido las longitudes, cantidad de
operandos y tipos de direccionamiento a utilizar en cada una, no resta más que asignar cada uno de
ellos, bit a bit, a la cadena de bits que representará cada instrucción y que será almacenada en una
posición de la memoria del programa.

Normalmente, el código de operación (codop) representa los primeros bits. Para el caso de estudio
identificamos que con 4 instrucciones se puede solucionar el problema inicial, y por lo tanto el codop
es de solo dos bits. Posteriormente van los operandos, cuya longitud puede variar de acuerdo al modo
de direccionamiento utilizado; si la instrucción utiliza direccionamiento a los registros, para el caso de
estudio requiere 3 bits (se definieron 8 registros), si se usa direccionamiento Inmediato, se definen
6 bits para ingresar el valor constante a operar y si se usa direccionamiento directo, se definen
6 bits para almacenar la dirección en memoria que requiere la instrucción. Así pues, se tienen 4
instrucciones, con máximo 3 operandos que pueden manejar direccionamiento de registro, inmediato
o directo según cada caso. Finalmente, se definió una longitud fija de 14 bits para cada instrucción del
conjunto de instrucciones del caso de estudio.

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 10
3.3. Codificación de las instrucciones

Gracias al análisis anterior, se puede generar un código binario de 14 bits para representar cada
instrucción diseñada. Para proveer toda la información de la programación del procesador al
usuario desarrollador, el conjunto de instrucciones se debe documentar minuciosamente, en lo
que constituye el manual del conjunto de instrucciones, que todo procesador pone a disposición
de sus usuarios. En la Tabla 2 se muestra el diseño técnico de las instrucciones propuestas con su
codificación bit a bit.

Tabla 3. Conjunto de instrucciones incluyendo el tipo y el formato de instrucción

Instrucción Tipo OpCode Op1 Op2 Op3 Otros

Aritmético- reg valor bas


cargar 00 valor (6 bits)
Lógica (3 bits) (2bits) (1bit)

reg1 reg2 etiqueta


brMay Salto 10 0 bits
(3 bits) (3 bits) (6 bits)

Aritmético- regd regf1 regf2


sumar 01 bas (3 bits)
Lógica (3 bits) (3 bits) (3 bits)

saltar Salto 11 Basura (6 bits) etiqueta (6 bits)

Fuente: elaboración propia

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 11
4. Diseño de algoritmos en bajo nivel
Finalmente, en este punto no resta más que convertir el algoritmo de alto nivel al lenguaje
ensamblador diseñado para el procesador del caso de estudio. A continuación, se presenta el diseño
funcional de las instrucciones que se han considerado, a nivel técnico en las secciones anteriores.

Teniendo muy claro el significado técnico y funcional de cada instrucción, y conociendo los conceptos
teóricos que se han presentado hasta ahora, la transcripción de alto a bajo nivel no debería ser
compleja. A continuación, se ilustra la transcripción al lenguaje ensamblador previamente diseñado
del algoritmo en alto nivel del caso de estudio.

Figura 1. Diseño del algoritmo en lenguaje ensamblador a partir del conjunto de instrucciones y el algoritmo en alto nivel
Fuente: elaboración propia

¿Sabía que...?
En este procesador las constantes se manejan en formato decimal. Por lo tanto, 10
corresponde a diez, y no a 10 en binario (2).

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 12
Por último, solo resta decir que una conversión más se realiza, y es entre el lenguaje ensamblador y el
lenguaje de máquina (sistema binario) que entiende el procesador. Normalmente esta conversión la
realizan los compiladores, reemplazando los mnemónicos por sus respectivos codops y los valores y
direcciones por su equivalente en binario. A modo ilustrativo, a continuación se presenta la versión en
código de máquina del algoritmo del caso de estudio.

Tabla 4. Programa desarrollado en binario y en Hexa

# Instrucción en binario HEX


0 00 000000 001 01 0 00000000001010 000A
1 00 000000 001 01 0 00000010010100 0094
2 00 000000 011 01 0 00000000011010 001A
3 00 000000 100 01 0 00000000100010 0022
4 10 011 010 001000 10011010001000 2688
5 01 011 011 001 000 01011011001000 16C8
6 01 100 100 001 000 01100100001000 1908
7 11 000000 000100 11000000000100 3004

Fuente: elaboración propia

En síntesis...
En lenguaje de máquina todas las variables, valores y expresiones se
expresan en sistema binario. Se debe prestar especial atención a los
modos de direccionamiento que se utilizan para invocar cada operando y
mecanizar cómo los saltos, jumpsobranchs, alteran el flujo de ejecución
del programa para crear ciclos o condicionales. Son éstos los aspectos que
distan en mayor medida entre el lenguaje de alto y bajo nivel. Practicando
el desarrollo en lenguaje ensamblador verás cómo estos puntos clave se
van manejando con mayor naturalidad.

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 13
Referencias
Gosling, J., Joy, B., Steele, G., Bracha, G., & Buckley, A. (13 de Febrero de 2015). The Java language
specification Java SE 8 edition. Obtenido de https://docs.oracle.com/javase/specs/jls/se8/jls8.pdf

Stallings, W. (2005). Organización y arquitectura de computadores. Madrid: Pearson Educación.

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 14
INFORMACIÓN TÉCNICA

Módulo: Arquitectura del Computador


Unidad 2: ISA: Instruction Set Architecture y Aritmética
para procesadores.
Escenario 4: Diseño de un lenguaje ensamblador

Autor: Laura Juliana Cortés Rico

Asesor Pedagógico: Edwin Alcides Mojica Quintero


Diseñador Gráfico: Carlos Montoya
Asistente: Ginna Quiroga

Este material pertenece al Politécnico Grancolombiano. Por


ende, es de uso exclusivo de las Instituciones adscritas a la Red
Ilumno. Prohibida su reproducción total o parcial.

POLITÉCNICO
POLITÉCNICO GRANCOLOMBIANO
GRANCOLOMBIANO 15

También podría gustarte