Está en la página 1de 30

Arquitectura

de Computadores

3. Lenguaje Máquina
1. Visión del Programador
2. Formato de las Instrucciones
3. Modos de Direccionamiento
4. Instrucciones Típicas
5. Un Ejemplo: Motorola 68000

Arquitectura de Computadores Lenguaje Máquina - 1

En el capítulo anterior hemos visto la interfaz hardware que ofrece la CPU, esto es, los elementos
que ofrece para conectarla con el resto de los componentes de un ordenador. Ahora abordaremos
la interfaz software, o lo que es lo mismo, lo que necesitan saber los programadores o
constructores de compiladores para poder escribir programas capaces de ejecutarse en la CPU.
Esta interfaz software muestra aspectos como el repertorio y formato de las instrucciones que
ofrece, con sus variados modos de direccionamiento para acceso a los operandos. Pero para
poder escribir programas para una CPU también se necesita conocer otros aspectos como los
registros internos, estructura o visión de la memoria y los tipos de datos que maneja directamente
la ALU.
Después de dar una introducción general a estos aspectos, se verá con cierto detalle un caso
concreto: el procesador 68000 de Motorola.

Arquitectura de Computadores Lenguaje Máquina - 1


Lenguaje Máquina Visión del Programador

Visión del
Hardware CPU Memoria
PC $0000
0400
SP 10FF $0001
SR
R0 $0400
... prog.

$0B00 2y
Rn datos
$1000
pila

Bus Bus
Datos Dir. $10FF
(x bits) (y bits) $FFFF

x
Arquitectura de Computadores Lenguaje Máquina - 2

El programador más inmediato de un ordenador trabaja a muy bajo nivel, pues ve el hardware muy
de cerca. Los programas los tiene que escribir en lenguaje máquina o, normalmente, en
ensamblador, es decir, una representación nemotécnica del lenguaje máquina en la que cada
instrucción ensamblador se corresponde con una instrucción máquina.
¿Qué tiene que conocer este programador de ensamblador o de lenguaje máquina para escribir
programas para el ordenador? La respuesta es “Algo de hardware y algo de software”.
1) Algo de hardware:
• Algunos detalles de la CPU:
- Registros generales y de control (Contador de Programa,
Puntero de Pila, Registro de Estado, ...).
- Tamaño de los registros generales, para saber el rango de los
números que se pueden manejar.
• Tamaño de la memoria

Arquitectura de Computadores Lenguaje Máquina - 2


Lenguaje Máquina …Visión del Programador

Visión del
Software Pila
E1
Juego de Instrucciones
Nemotécnico Cod. Máquina 50
move #3,R2 11000111 ($C7)
2B
add R2,R3 00110110 ($36)
...
9A
...
sub #1,R2 01100110 ($66)

- Meter
LIFO
- Sacar

Arquitectura de Computadores Lenguaje Máquina - 3

2) Algo de software:
• El juego de instrucciones
• Organización de la pila (si la hay).

Estos elementos de hardware y de software son con los que cuenta el programador para escribir
sus programas, o lo que es lo mismo, ésta es la visión del programador del ordenador básico.
En resumen, cuenta con una memoria donde almacena su programa (con las instrucciones y los
datos) y una CPU que es capaz ejecutar las instrucciones del programa, ayudándose para ello de
registros internos a los que trae los operandos desde la memoria principal, y de una pila para
guardar ciertos datos temporales.
Puesto que ya conocemos la estructura básica de una CPU, en este capítulo vamos ocuparnos del
lenguaje máquina, es decir, del formato que pueden tener las instrucciones máquina, de los modos
de direccionamiento disponibles para acceder a los operandos indicados en las instrucciones y, por
supuesto, de los distintos tipos de instrucciones que suelen ofrecer los procesadores de propósito
general (al menos los de tipo CISC).
Al final del capítulo particularizaremos todo esto para el microprocesador de Motorola MC68000,
comentando su estructura general, organización de la memoria, su pila y, por supuesto, su juego
de instrucciones.

Arquitectura de Computadores Lenguaje Máquina - 3


Lenguaje Máquina Formato de las Instrucciones

Cod. Op.

Cod. Op. Operando

Cod. Op. Operando 1 Operando 2

- Valor
- Dirección · memoria

· registro

Arquitectura de Computadores Lenguaje Máquina - 4

Una instrucción máquina es una secuencia de bits que indica una operación que debe realizarse y
con qué operandos debe realizarse.
Los operandos son datos que están en alguno de los registros internos de la CPU, en la memoria
principal o en algún controlador de entrada/salida.
Una instrucción siempre realiza alguna acción sobre algún o algunos operandos. Estos pueden
estar indicados implícita o explícitamente en la instrucción máquina.
Un operando está implícito en una instrucción cuando el propio código de operación establece
sobre qué actúa la operación. En este caso, tal operando es fijo, es decir, el programador no puede
establecer que esa instrucción actúe con otro operando distinto.
Cuando una instrucción puede operar con diversos operandos posibles, a elegir por el
programador, los operandos elegidos deben figurar de manera explícita (separados del código de
operación) en la instrucción máquina.
Si una instrucción utiliza varios operandos, estos pueden ser una mezcla de operandos implícitos y
explícitos.
El formato de una instrucción máquina define la disposición y el reparto de sus bits entre los
componentes de la instrucción, esto es, el código de operación y los operandos.
Una instrucción máquina debe incluir el código de operación y, si los tiene, uno o más operandos
explícitos. A cada operando explícito se accede mediante uno de los distintos modos de
direccionamiento que veremos en el siguiente apartado.
Como veremos más tarde (al comentar los distintos tipos de instrucciones que se suelen encontrar
en los procesadores de propósito general) ya que hay instrucciones con uno, dos, tres o ningún
operando explícito, es normal que los juegos de instrucciones estén compuestos por instrucciones
con distintos formatos. En el formato de cada instrucción se suele indicar implícita o explícitamente
el modo de direccionamiento de cada uno de sus operandos.

Arquitectura de Computadores Lenguaje Máquina - 4


Lenguaje Máquina Cuestiones de Diseño
Longitud de Instrucción
Muchos códigos de operación
Instrucción
Muchos modos de direccionamiento más larga
Gran espacio de direcciones
Long. instrucción múltiplo de palabra Más memoria
Más lento
Reparto de Bits
¿Cuántos códigos de operación?
¿Cuántos operandos?
¿Dónde están los operandos?
¡ COMPROMISO !
¿Cuántos registros hay?
¿Cuántos modos de direccionamiento?
¿Granularidad de las direcciones?
Arquitectura de Computadores Lenguaje Máquina - 5

A la hora de diseñar un juego de instrucciones, se deben tener en cuenta ciertas consideraciones sobre dos
cuestiones: la longitud de la instrucción y el reparto de los bits que la componen.
Longitud de la instrucción. Hay un claro compromiso entre el deseo de un rico y variado repertorio de instrucciones,
y la necesidad de ahorrar espacio. Los programadores quieren muchos códigos de operación distintos (requiere
muchos bits en el campo de código de operación) para disponer de operaciones que se ajusten lo más posible a sus
necesidades, y así escribir programas más cortos. De igual manera, cuantos más modos de direccionamiento estén
disponibles, más flexibilidad tendrán para manejar estructuras de datos complejas, como tablas o matrices. Por otro
lado, puesto que cada vez se dispone de mayor cantidad de memoria, se requieren muchos bits para hacer referencia
a un gran espacio de direccionamiento. Pero claro, una instrucción que ofrezca todo esto puede ocupar 32 bits,
posiblemente, el doble que otra similar que no ofrezca tanta flexibilidad. Está claro que una instrucción larga ocupa más
espacio en memoria que una corta, se tarda más tiempo en llevarla de memoria a la CPU, y se tarda más tiempo en
decodificarla.
Se debe tener en cuenta que el ancho del bus de datos sea múltiplo de la longitud de un carácter, para evitar
desaprovechar el espacio de almacenamiento. Y esta restricción afecta a la longitud de las instrucciones, que deben
ocupar un número entero de palabras, o en una palabra debe caber un número entero de instrucciones. Por esto los
tamaños de las instrucciones suelen ser múltiplos de 8. Un diseño con caracteres de 9 bits, instrucciones de 12 y
palabras de 31 bits sería una catástrofe.
Reparto de los bits. Aquí el compromiso está en el reparto de los bits disponibles entre el número de códigos de
operación y la versatilidad de los operandos. Esta versatilidad genera las siguientes preguntas: ¿cuántos operandos
hay en la instrucción?, ¿de cuántos modos de direccionamiento se dispone?, ¿dónde están los operandos, en registros
o en memoria?, ¿cuántos registros hay?.
El direccionamiento a memoria también plantea una pregunta: ¿cuál es la granularidad de las direcciones?. Es decir,
¿a dónde apunta cada dirección, a un byte, a una palabra de 16 bits, a una palabra de 32 bits, ...? Si el grano es de 1
byte, para direccionar una memoria de 64 Kb se requieren 16 bits, mientras que si el grano fuera una palabra de 4
bytes, solo se necesitarían 14 bits, lo cual significa instrucciones más cortas, menor espacio para el programa, y un
menor tiempo para alimentar la instrucción. Sin embargo, tiene la pega de que para obtener un carácter de memoria
hay que acceder a la palabra completa, y luego en la CPU seleccionar la parte deseada, lo cual consume tiempo.

Arquitectura de Computadores Lenguaje Máquina - 5


Lenguaje Máquina Códigos de Operación con Extensión

OTRO CASO
Intel -Motorola
Instrucciones de 16 bits
Instrucción de
Longitud variable Hasta 3 operandos en 16 registros

Hasta 16 operaciones distintas

PowerPC ¡ PERO NECESITAMOS !

Formato fijo 15 Instrucciones de 3 operandos


14 “ de 2 “
C. op. Operandos
31 “ de 1 “
6 26
16 “ sin operandos

¿Cómo?
Arquitectura de Computadores Lenguaje Máquina - 6

Debido a los compromisos que acabamos de ver, normalmente todos los juegos de instrucciones son de longitud
variable, es decir, disponen de diversos formatos de instrucción, con distintas longitudes que se adaptan a las
necesidades de la instrucción. Por esto, es normal encontrarse que en una misma máquina hay instrucciones de 1, 2, 3
y 4 o más bytes de longitud (eso sí, siempre con un tamaño múltiplo de 8 bits).
El Pentium de Intel, tiene instrucciones de longitud variable, y pueden llegar a tener un tamaño de hasta 12 bytes. El
PowerPC, por el contrario, tiene un juego de instrucciones con un formato regular de 32 bits, donde los 6 primeros
corresponden al código de operación.
Hasta ahora hemos supuesto que una vez decidido el número de bits reservado para el código de operación, tanto este
número como el reservado para los operandos es fijo. Por ejemplo, si una CPU ofrece 100 instrucciones, parece que el
código de operación debe tener reservados 7 bits en la instrucción. Pero en algunas arquitecturas en las que las
instrucciones son de longitud fija (como en el PowerPC), puede resultar conveniente hacer variable el tamaño del
código de operación, para acomodarse a las necesidades de la instrucción. Veámoslo con un ejemplo.
Supongamos una máquina con instrucciones de 16 bits, que realiza operaciones hasta con 3 operandos, y que éstos
siempre están en alguno de sus 16 registros. Esto quiere decir que se necesitan 4 bits por operando, y que si puede
haber hasta 3 operandos, se necesitan 12 bits para ellos. Esto nos deja con 4 bits para códigos de operación, lo que
significa que puede haber hasta 16 operaciones distintas con 3 operandos.
Pero resulta que lo que se desea es un juego con 15 instrucciones de 3 operandos, 14 instrucciones de dos operandos,
31 de un operando, y 16 instrucciones sin operandos. ¿Cómo hacerlo? Con Códigos de Operación con Extensión.
En la siguiente transparencia tenemos la solución.

Los códigos de operación con extensión son bastante comunes. No solamente los utilizan procesadores con formatos
instrucción de longitud fija, como el PowerPC, sino los de longitud variable como el 80386, 80486 y Pentium de Intel, y
la familia 68000 de Motorola.

Arquitectura de Computadores Lenguaje Máquina - 6


Lenguaje Máquina …Códigos de Operación con Extensión
15 instrucciones 31 instrucciones
de 3 operandos de 1 operando
Cod. Op. 0000 XXXX YYYY ZZZZ Cod. Op. 1111 1110 0000 XXXX
de 4 bits 0001 XXXX YYYY ZZZZ de 12 bits 1111 1110 0001 XXXX
0010 XXXX YYYY ZZZZ . . .
. . . 1111 1110 1111 XXXX
. . . 1111 1111 0000 XXXX
. . . 1111 1111 0001 XXXX
1101 XXXX YYYY ZZZZ . . .
1110 XXXX YYYY ZZZZ 1111 1111 1101 XXXX
1111 1111 1110 XXXX

16 instrucciones
14 instrucciones
sin operandos
de 2 operandos Cod. Op. 1111 1111 1111 0000
Cod. Op. 1111 0000 XXXX YYYY
de 16 bits 1111 1111 1111 0001
de 8 bits 1111 0001 XXXX YYYY 1111 1111 1111 0010
1111 0010 XXXX YYYY . . .
. . . . . .
. . . 1111 1111 1111 1101
. . . 1111 1111 1111 1110
1111 1100 XXXX YYYY 1111 1111 1111 1111
1111 1101 XXXX YYYY

Arquitectura de Computadores Lenguaje Máquina - 7

15 instrucciones de 3 operandos.
Comencemos con el formato de las 15 instrucciones de 3 operandos de 4 bits. No tenemos ningún problema, pues para representar
15 códigos de operación se requieren 4 bits, y los 12 bits restantes se utilizan para los tres operandos de 4 bits.
Así, los códigos de operación serán el 0000, 0001, ..., hasta el 1110. ¡Y nos sobra una combinación de las 165 que ofrecen 4 bits!

14 instrucciones de 2 operandos.
La combinación que nos sobraba del formato anterior (la 1111) la utilizaremos ahora para indicar un nuevo formato de instrucción.
Es decir, las instrucciones cuyos 4 bits de mayor peso sean 1111 tendrán un código de operación extendido con los 4 bits
siguientes. En este nuevo formato, el código de operación ocupa 8 bits, donde los 4 de mayor peso están siempre a 1. Los ocho
bits restantes se utilizan para indicar los dos operandos de este formato.
Ahora nos encontramos con que también nos sobran dos combinaciones: 1111 1110 y 1111 1111. Las aprovecharemos.

31 instrucciones de 1 operando.
Si los cuatro bits de mayor peso a 1 indican que el código de operación se extiende o amplía con otros cuatro, cuando los 7 bits de
mayor peso son 1111 111, indica que el formato de tales instrucciones está formado por un código de operación de 12 bits (los de
mayor peso). Los cuatro bits restantes se utilizan como operando.
Para este formato disponemos ahora de 5 bits para expresar 31 nuevas instrucciones, las que tienen los códigos desde 1111 1110
0000 hasta 1111 1111 1110. Ahora nos sobra una combinación de las disponibles.

16 instrucciones sin operandos explícitos.


Como vamos viendo, el que sobre alguna combinación no es casualidad o buena suerte, simplemente es que es necesario para
poder seguir extendiendo el código de operación. Ahora nos encontramos con que los doce bits de mayor peso a 1 indican un
nuevo formato de instrucción con un código de operación de 16 bits.
Los cuatro bits de la ampliación son los que nos ofrecen los últimos 16 códigos de operación para las instrucciones sin operandos
explícitos.

Cuando se planifican formatos de instrucciones con códigos de operación con extensión, para cada formato, se debe reservar
alguna de las combinaciones posibles para expresar una extensión en el código de operación.

Arquitectura de Computadores Lenguaje Máquina - 7


Lenguaje Máquina Modos de Direccionamiento
 ¿Dónde se Ubican los Operandos?
En la Instrucción
ADD #7,R4,$FF1234 ☺ Rápido y simple
Sólo constantes
No para resultados

En Memoria Principal
Muchos bits

En Registros de la CPU
☺ Se requieren pocos bits
☺ Rápido acceso
Pocos registros
Hay que cargar los registros

Arquitectura de Computadores Lenguaje Máquina - 8

El diseño cuidadoso de los códigos de operación es una parte importante del juego de instrucciones de una máquina.
No obstante, la mayor parte de los bits de una instrucción se utilizan para especificar los operandos de la operación,
por lo que también debe afrontarse con mucho cuidado el modo de direccionar los operandos de las instrucciones.
Vamos a considerar ahora dos factores sobre los operandos a tener en cuenta en el diseño del formato de las
instrucciones:
• Dónde poner los operandos
• Cuántos operandos se indican en la instrucción

Los operandos pueden estar en tres sitios:


• En la propia instrucción
• En registros de la CPU
• En memoria principal
Con el operando en la misma instrucción, parece claro que el acceso a él es simple y rápido, no obstante estos
operandos solamente pueden ser constantes, pues su valor se establece en tiempo de compilación; por esto mismo,
tampoco se pueden utilizar como operandos de destino o de resultado. Así, si las variables están ubicadas en memoria
principal, parece conveniente utilizar el campo de operando para indicar su dirección en memoria principal, sin
embargo, para los procesadores actuales, es normal disponer de un bus de direcciones de 32 bits, lo que implica que
el campo de operando en la instrucción requiere también 32 bits, y si consideramos una instrucción con tres operandos
más el código de la operación, la longitud de la instrucción se dispara. Una alternativa puede ser utilizar registros
generales para contener los operandos. Así, en una máquina con 8 registros se necesitan solamente 3 bits para
indicar uno de ellos en el campo de operando. Esto tendría la mejora añadida de que el acceso a un registro es mucho
más rápido que a memoria principal. Pero también tiene pegas. Una es que si se dispone de pocos registros generales
y se ubican en ellos las variables, se pueden agotar enseguida. Por esto, las arquitecturas recientes tienden
proporcionar un número generoso de registros. Otra pega es que para operar con operandos en registros, previamente
hay que cargarlos desde memoria principal, lo que significa ejecutar instrucciones adicionales con direcciones de
memoria (largas y costosas). Por esto, solamente merece la pena cargar los operandos en registros cuando se van a
utilizar repetidamente (lo cual suele ser lo más habitual).

Arquitectura de Computadores Lenguaje Máquina - 8


Lenguaje Máquina …Modos de Direccionamiento
 ¿Cuántos Operandos se Indican en la Instrucción?

Todos
ADD $FF1234,$FFF123,$FFFF12
Requiere muchos bits

Reutilizar Alguno
ADD $FF1234,$FFF123

Omitir Alguno (Implícitos)


- En Acumulador: ADD $FF1234
- En la Pila: PUSH R1

Arquitectura de Computadores Lenguaje Máquina - 9

En cuanto al número de operandos, algunas instrucciones pueden requerir tres operandos, como
la suma (dos sumandos y un resultado), lo cual puede resultar en un exceso de bits. Por ello, la
mayoría de este tipo de instrucciones suele utilizar como resultado uno de los mismos operandos,
ahorrando así espacio en la instrucción. Otra posibilidad consiste en no indicar los operandos
explícitamente en la instrucción, utilizando directamente ciertos operandos de forma implícita. Así,
algunas máquinas indican un único operando para realizar una suma, y lo que hacen es añadir el
contenido de ese operando al de un registro especial llamado acumulador, y el resultado lo dejan
también en el acumulador. El problema que presenta esta última técnica es que cuando hay
muchos cálculos, hay que estar constantemente cargando y salvando el contenido del acumulador,
lo cual requiere espacio de instrucciones y tiempo de ejecución. Otro modo de indicar operandos
implícitos es con los direccionamientos orientados a Pila que veremos en las siguientes
transparencias.

Arquitectura de Computadores Lenguaje Máquina - 9


Modos de Direccionamiento Inmediato

MOV_AC #47

C. Op. Operando

Constantes “pequeñas”
Números en complemento a dos
☺ Sin referencias a memoria

Arquitectura de Computadores Lenguaje Máquina - 10

Como ya hemos mencionado, el espacio disponible para los operandos en una instrucción suele
estar bastante limitado. También sabemos que los datos con los que hay que operar pueden
encontrarse en los registros del procesador, en variables de la memoria principal o en la pila. Por
otra parte, dependiendo de la complejidad de las estructuras de datos manejadas se puede hacer
necesaria la utilización de modos de direccionamiento más o menos complejos. Algunas veces el
modo del direccionamiento viene indicado implícitamente por el código de operación, que fuerza el
modo de direccionamiento, en otros casos el modo debe indicarse explícitamente en cada
operando.
Vamos a dedicarnos ahora a tratar algunos modos de direccionamiento más comunes que suelen
encontrarse en los procesadores de propósito general. Aunque hay múltiples variaciones, todas
ellas suelen estar basadas en los modos que vamos a tratar a continuación.

Direccionamiento Inmediato
La forma más simple de indicar un operando es incluyéndolo en la propia instrucción. Ya que las
instrucciones no son modificables, este es el modo que se utiliza en operaciones con constantes.
Si la constante es un valor numérico, se almacena en complemento a dos.
La ventaja del direccionamiento inmediato es que no se requieren referencias adicionales a
memoria para obtener el operando, ahorrando por lo tanto espacio y tiempo. El inconveniente es
que el espacio reservado para este operando suele estar restringido y suele ser menor que el
tamaño de la palabra, por lo que en algunos procesadores solamente se utiliza para constantes de
valores pequeños.

Arquitectura de Computadores Lenguaje Máquina - 10


Modos de Direccionamiento Directo

INC $10B0
C. Op. dddddddddddddddd ....

operando

Para las variables globales


MEMORIA
Una referencia adicional a memoria
Requiere muchos bits

Arquitectura de Computadores Lenguaje Máquina - 11

Direccionamiento Directo (o absoluto)


Otra forma muy simple de hacer referencia a un operando es indicando su dirección en memoria
principal, y solamente requiere una referencia adicional a memoria para obtener el operando. Es el
modo de direccionamiento común para las variables globales de los programas.
La pega que tiene es que cuando se dispone de grandes espacios de direccionamiento, requiere
muchos bits para indicar la dirección, como es el caso de Motorola. En el Pentium de Intel, se
utiliza hasta un máximo de 32 bits para indicar la dirección del operando en memoria.

Arquitectura de Computadores Lenguaje Máquina - 11


Modos de Direccionamiento A Registro

INC R2
Registros
C. Op. rrrr .... de la CPU

operando

Valores temporales o muy


referenciados
☺ Sin referencias a memoria
☺ Requiere pocos bits
Suele haber pocos registros

Arquitectura de Computadores Lenguaje Máquina - 12

Direccionamiento a Registro
Este modo es similar al direccionamiento directo, pero en este caso, el campo de dirección se
refiere a uno de los registros generales del procesador.
Las ventajas que tiene es que solo necesita 3 o 4 bits para indicar uno de los registros generales, y
que no requiere referencias adicionales a memoria. El inconveniente es que no se suele disponer
de muchos registros, aunque con el advenimiento de las máquinas RISC, la tendencia es a ir
incrementando su número.
Se utiliza para guardar valores temporales en la evaluación de expresiones, o para mantener en
registros algunas variables que se referencian muy a menudo.

Arquitectura de Computadores Lenguaje Máquina - 12


Modos de Direccionamiento Indirecto

INC_IND R7
C. Op. rrrr .... Memoria

dddddd operando
Registros
de la CPU

Cuando no se conoce la dirección del dato


en tiempo de compilación
Requiere múltiples accesos

Arquitectura de Computadores Lenguaje Máquina - 13

Direccionamiento Indirecto
Si en el direccionamiento directo, el campo de operando indicaba la dirección del dato, en el direccionamiento indirecto,
se hace referencia a una palabra de memoria principal en la que se encuentra la dirección del operando. La otra
posibilidad de este direccionamiento es que el campo de operando hace referencia a un registro general en el que se
encuentra la dirección del dato.
Como se puede apreciar, según este esquema, con una “indirección” se requieren dos accesos adicionales a memoria
para obtener el operando (si es vía registro, solo uno).
Este direccionamiento se utiliza cuando la dirección de las variables no se conoce en tiempo de compilación, sino que
es durante la ejecución del programa cuando se calcula la dirección del operando y se guarda ésta en memoria o en un
registro.
Los procesadores de Intel de la familia 80x86 y Pentium disponen de direccionamiento indirecto por registro, pero no a
través de memoria. Igual le sucede al MC68000 de Motorola. Su hermano mayor, el MC68020 también dispone de
direccionamiento indirecto vía memoria.
Una rara variante de este modo es el direccionamiento indirecto multinivel. En este caso, el primer bit de la palabra
direccionada indica si dicha palabra es ya la dirección efectiva del operando, o se debe aplicar un nuevo nivel de
indirección.

Supongamos que en una determinada máquina se dispone de dos operaciones para incrementar el valor de una
variable en memoria principal, una por direccionamiento directo, y otra por direccionamiento indirecto por memoria, es
decir, que ambas instrucciones constan de código de operación y de una dirección de memoria principal. ¿Cómo saber
cuándo se está utilizando la del direccionamiento directo o la del direccionamiento indirecto?
Hay dos maneras para diferenciarlas:
1) Teniendo códigos de operación distintos, que implícitamente indican el modo de direccionamiento.
2) Teniendo ambas el mismo código de operación, pero disponiendo en la instrucción de un campo que indica
explícitamente el modo de direccionamiento de cada operando.

¡Ojo! Dos instrucciones en ensamblador con el mismo nombre nemotécnico pueden generar instrucciones máquina
con distintos códigos de operación. Y al contrario, dos instrucciones en ensamblador con distinto nombre nemotécnico
pueden generar instrucciones máquina con el mismo código de operación y distintos modos de direccionamiento.

Arquitectura de Computadores Lenguaje Máquina - 13


Modos de Direccionamiento Por Desplazamiento

C. Op. rrrr dddddddddd


MEMORIA

bbbbbb +
operando

REGISTROS
 Relativo → CP
Para control de bucles
Según  Por Registro Base → Un Registro base
rrrr Para áreas de datos reubicables

 Indexado → Reg. de Índice


Para acceso a tablas
Arquitectura de Computadores Lenguaje Máquina - 14

Direccionamiento por Desplazamiento


Hay unos cuantos métodos de direccionamiento que para formar la dirección del operando utilizan el contenido de un
registro más un desplazamiento que viene explícitamente en el campo de operando.
A este mecanismo para formar la dirección del operando se le conoce también como base+desplazamiento. La base
está contenida en un registro, y el desplazamiento viene indicado por los bits del campo de operando.
En algunos casos, el registro base utilizado puede estar implícitamente impuesto por el código de operación.
Dependiendo del registro base utilizado, se distinguen los siguientes modos de direccionamiento por desplazamiento:
- Relativos. En este modo se utiliza el Contador de Programa, de tal modo que la dirección efectiva se calcula
añadiendo el desplazamiento que figura en el campo de operando más el contenido del Contador de Programa.
Este direccionamiento lo utilizan los compiladores para indicar las direcciones de salto en las instrucciones de
control de bucles.

- Por registro base. Este modo de direccionamiento se utiliza comúnmente en los programas reubicables. El
registro base contiene la dirección de una gran área de datos o de instrucciones. Y los bits del campo de
operando indican el desplazamiento del dato a partir del comienzo del área de datos indicado por el registro
base.
Además de permitir programas reubicables, constituye una buena alternativa al direccionamiento directo, pues
requiere pocos bits en el campo de operando.

- Indexado. El propósito de este modo de direccionamiento es facilitar el acceso iterativo a las matrices o tablas de
datos. Lo que se hace es indicar en los bits del campo de operando la dirección inicial de la tabla, y a esta
dirección se le añade el contenido de un registro llamado “registro de índice”. Para ir referenciando los
sucesivos elementos de la tabla simplemente hay que ir incrementando el contenido del registro de índice.

Arquitectura de Computadores Lenguaje Máquina - 14


Modos de Direccionamiento A Pila

Último en entrar - Implícito (PP)


Primero en salir Direccionamiento
- Explícito

Cima
66 66
(PP)
Cima Cima
55 55 55
(PP) (PP)
Cima
44 44 44 44
(PP)
33 33 33 33
66
22 22 22 22
Base 11 11 11 11 Ac

MEMORIA Push 55 Push 66 Pop


PRINCIPAL
Arquitectura de Computadores Lenguaje Máquina - 15

Direccionamiento a Pila
La Pila es una estructura de datos que se mantiene en memoria principal. Básicamente es un
vector de celdas de datos de direcciones secuenciales, en los que se meten y sacan datos con
política LIFO (Last In, First Out), es decir, el último en entrar es el primero en salir.
Esta estructura es muy útil como ayuda en la ejecución de los programas, pues se utiliza para
guardar en ella variables temporales, parámetros, direcciones de retorno en la llamada a
procedimientos, etc.
El primer elemento que se mete en la pila se dice que esta en el fondo de la pila, y el último que se
ha metido está en la cima de la pila. El interés de la cima de la pila es que siempre está en ella el
primer dato disponible de la pila. Las operaciones con la pila son meter y sacar datos de ella, y
operan utilizando un registro denominado puntero de pila que siempre contiene la dirección de la
cima de la pila.
En algunos procesadores, como el 68000, el registro de puntero de pila es simplemente uno de los
registros generales que se utilizan para direcciones, y se accede a la pila mediante instrucciones
de movimiento de datos y el ya comentado direccionamiento indirecto por registro. Los
procesadores de Intel disponen de un registro específico: el Puntero de Pila, que siempre está
apuntando a la cima de la pila, y se ofrecen instrucciones específicas para meter y sacar datos de
la pila (PUSH y POP) en las que ni siquiera se indica explícitamente el registro de indirección, pues
está implícito por el código de operación.

Tanto en Motorola como en Intel, la Pila es una estructura de datos que, en contra de la intuición,
crece de las direcciones altas hacia las bajas, es decir, que la cima de la Pila siempre está en una
dirección más baja que la base de la Pila (salvo cuando la Pila está vacía, claro).

Arquitectura de Computadores Lenguaje Máquina - 15


Modos de Direccionamiento Ejemplo - Resumen

Modo
Inmediato #1234 1130
R0 1234
Directo a registro R0
R1 130
Absoluto 1132 1132 1234
R2 1132
Indirecto por registro (R2) ...
R3 1132
Indirecto por memoria (6003) ...
R4 -6
Indexado 1138(R4) 6000 1130
R5 1133
Pre-decremento -(R5) R6 1100
Post-incremento (R3)+ R7 32
6003 1132
Reg. base + desplazamiento 32(R6)
Relativo al PC 130(PC) PC 1002
Memoria Principal
Relativo al PC indexado (PC,R1)

Arquitectura de Computadores Lenguaje Máquina - 16

En la transparencia se muestra la especificación de un operando con valor 1234 situado en la


propia instrucción (con direccionamiento inmediato), en el registro R0 (accesible mediante
direccionamiento directo a registro) y en la dirección de memoria principal 1132 (accesible
mediante direccionamiento directo a memoria o absoluto).
Como se puede comprobar con este ejemplo, también hay otros variados modos de
direccionamiento a través de los cuales se obtiene el valor 1234 del operando.
Se puede acceder a este operando mediante direccionamiento indirecto a través del registro R2, o
de la dirección de memoria 6003.
Mediante direccionamiento indexado se obtiene igualmente la dirección del operando añadiendo el
desplazamiento 1138 al contenido del registro R4. De forma similar se obtiene la dirección con el
modo de registro base más desplazamiento.
El direccionamiento relativo al PC también es similar al indexado o indirecto con desplazamiento,
salvo que el registro utilizado es el PC. En la variante indexada, la dirección del operando se
obtiene sumando el contenido del PC más el registro de índice R1.
Para la gestión de la pila, los procesadores suelen ofrecer o bien instrucciones específicas (como
push y pop) o bien direccionamientos apropiados, como es el caso del Motorola 68000, mediante
los modos con pre-incremento y post-decremento. Con instrucciones de movimiento o copia de
datos y estos direccionamientos se emula el comportamiento de las instrucciones push y pop.
Consúltense los direccionamientos del Motorola 68000 para ver cómo funcionan estos
direccionamientos con pre-decremento y post-incremento.

Arquitectura de Computadores Lenguaje Máquina - 16


Lenguaje Máquina Instrucciones Típicas

 Transferencia de Datos Ejecución de la Instrucción


 Aritméticas Operandos
 Lógicas
 Transferencia de Control Registro
ALU de
 Control del Sistema Estado

Resultado

0, 1, 2, n
Operandos
Ortogonalidad En Registros Longitud de
En Memoria Instrucción

Arquitectura de Computadores Lenguaje Máquina - 17

Aunque el número de instrucciones que se ofrece varía de máquina a máquina, en todas ellas
suelen encontrarse los mismos tipos de instrucciones:
• Transferencia de datos
• Aritméticas
• Lógicas
• Transferencia de Control
• Control del sistema
Muchas de estas instrucciones utilizan dos operandos, y dependiendo de la versatilidad u
ortogonalidad de la máquina, pueden permitir que ambos operandos estén solamente en registros
generales, uno en registro y el otro en memoria, o los dos en memoria. Obviamente, siempre hay
un compromiso entre la máxima ortogonalidad (cualquier mezcla de modos de direccionamiento),
con la correspondiente longitud de instrucción que ello conlleva.
En general, Intel y PowerPC suelen ofrecer instrucciones en las que no permiten todos los tipos de
direccionamiento en una misma instrucción (por ejemplo, direccionamiento directo para ambos
operandos), sobre todo en el caso del PowerPC, que es un procesador RISC. En cambio Motorola
ofrece un juego de instrucciones más ortogonal, claro está, a cambio de tener instrucciones de
hasta 10 bytes de longitud.
Otra cuestión que se debe tener en cuenta es que una gran parte de las instrucciones modifican o
establecen los flags de estado del Registro de Estado, indicando si la última operación ha
producido overflow, si un resultado es cero, positivo o negativo, etc.

Arquitectura de Computadores Lenguaje Máquina - 17


Instrucciones Típicas Transferencia de Datos (Copia)

MOVE OP_fuente,OP_destino
Op_destino := Op_fuente

Operandos en:
• Registro
• Memoria
• Pila
• Inmediato

Cargar: Memoria → Registro


Almacenar: Registro → Memoria

Arquitectura de Computadores Lenguaje Máquina - 18

Transferencia de Datos
En realidad no son instrucciones de transferencia o movimiento de datos, sino simplemente de
copia. Es uno de los tipos de instrucciones más fundamentales. Estas instrucciones tienen dos
operandos, el fuente y el destino, y deben copiar el contenido del operando fuente al de destino.
Por tanto, deben indicar la ubicación o dirección de ambos operandos, que pueden estar en un
registro, en memoria o en la pila. (El operando fuente también puede ser un operando inmediato
incluido en la propia instrucción).
A las instrucciones de copia de memoria a registro se las suele llamar “de carga”, mientras que las
que copian de registro a memoria se denominan “de almacenamiento”.

Arquitectura de Computadores Lenguaje Máquina - 18


Instrucciones Típicas Aritméticas

ADD OP_1,OP_2
Op_1 := Op_1 + Op_2

Suma, Resta,
- Coma Fija y Flotante
Multiplicación,
División - Truncamientos

Inc, Dec, Abs, Not - Redondeos

Arquitectura de Computadores Lenguaje Máquina - 19

Aritméticas
Todos los procesadores de propósito general proporcionan las operaciones básicas aritméticas de
suma, resta, multiplicación y división, siempre, al menos, para números enteros de coma fija. Los
procesadores de los últimos años también suelen incluir operaciones en coma flotante, y los
mainframes también manejan números decimales empaquetados.
Las instrucciones aritméticas suelen ofrecerse con distintas precisiones, y no debe olvidarse que
pueden producirse resultados con truncamiento o redondeo.
Otras instrucciones aritméticas comunes son: incrementar, decrementar, valor absoluto y valor
negado.

Arquitectura de Computadores Lenguaje Máquina - 19


Instrucciones Típicas Lógicas

OR OP_1,OP_2
Op_1 := Op_1 OR Op_2

Op. Booleanas: OR, AND, XOR, NOT


Manejo de bits

Transformación de formato

Arquitectura de Computadores Lenguaje Máquina - 20

Lógicas
También es normal ofrecer instrucciones para manejar los bits individuales de un byte o de una
palabra. Normalmente lo que hacen es realizar operaciones booleanas sobre bits, por lo que las
instrucciones ofrecidas suelen ser: OR, AND, OR exclusivo y NOT (negación).
Estas operaciones se aplican a bits individuales o a series de bits, de tal forma que si cada
operando es una serie de bits, la operación lógica se realiza entre el primer bit de la serie 1 y el
primer bit de la serie 2, entre el segundo bit de la serie 1 y el segundo bit de la serie 2, ...
Algunos autores incluyen dentro de las operaciones lógicas las operaciones de Transformaciones
de Formato, es decir, los desplazamientos y las rotaciones. Veámoslas en la siguiente
transparencia.

Arquitectura de Computadores Lenguaje Máquina - 20


Instrucciones Típicas Desplazamientos y Rotaciones
A Derechas A Izquierdas
Desp. Lógico
0 C C 0

Desp. Aritmético
S C C 0

Rotación
C C

Arquitectura de Computadores Lenguaje Máquina - 21

Desplazamientos y Rotaciones
Los desplazamientos y las rotaciones se aplican sobre un único operando, y pueden actuar a
derechas o a izquierdas.
Los desplazamientos pueden ser lógicos o aritméticos. El desplazamiento aritmético a la derecha
va replicando el bit de signo (el del extremo izquierdo) a medida que se va desplazando, por lo que
se mantiene el signo en el resultado. En el desplazamiento aritmético a izquierdas, el
desplazamiento no afecta al bit de signo, por lo que también se mantiene el signo en el resultado.
Como ya es sabido, el efecto aritmético de un desplazamiento a izquierdas es el de ir multiplicando
por las sucesivas potencias de 2, mientras que el desplazamiento aritmético a la derecha produce
la división por las sucesivas potencias de 2.
Ya que las rotaciones y los desplazamientos suelen afectar al bit de acarreo, estas instrucciones
sirven para analizar de forma individual los bits que componen un byte o una palabra de datos,
pues simplemente hay que consultar en cada momento el bit de acarreo para saber el valor que
tenía el último bit de la izquierda o la derecha antes de realizar la operación.

Arquitectura de Computadores Lenguaje Máquina - 21


Instrucciones Típicas Control del Sistema

 Establecer Privilegio
 Modificación del Registro de Estado
 RESET, HALT, ...

Arquitectura de Computadores Lenguaje Máquina - 22

Control del Sistema


Estas instrucciones no afectan a operandos de los programas de usuario, sino que tienen que ver
con el modo de ejecución del procesador, tales como el nivel de privilegio de ejecución (usuario,
supervisor), modificación del registro de estado, RESET, HALT, y otras que varían de unas
máquinas a otras.
Suelen ser instrucciones reservadas para los sistemas operativos, que solamente pueden
ejecutarse cuando el procesador está en modo “supervisor”.

Arquitectura de Computadores Lenguaje Máquina - 22


Instrucciones Típicas Transferencia de Control
A veces hay que romper el flujo
secuencial de las instrucciones
Bifurcaciones Control Llamadas a Interrupciones
If … Then Else de Bucles Procedimientos Excepciones

Saltos
Incondicionales Condicionales
JMP dirección
BEQ dirección
1º 2º
Establecer Bifurcar BNE dirección
Estado según Condición BHI dirección
(V,C,N,Z)
BLT dirección
ADD OP1,OP2
BCS dirección
CMP OP1, OP2
BVS dirección
TEST OP1

Arquitectura de Computadores Lenguaje Máquina - 23

Transferencia de control
Ya sabemos que el flujo natural de ejecución de las instrucciones es el orden lineal: se ejecuta la instrucción de la
siguiente dirección de memoria. No obstante, los programas tienen que modificar esa secuencialidad dependiendo de
ciertas situaciones o de los datos de entrada. También se hace necesaria la ruptura del flujo secuencial de control
cuando se realizan llamadas a procedimientos, que si bien mantienen una secuencialidad lógica, requieren un salto a
una instrucción distinta de la siguiente en secuencia.
Por esto se hace necesaria la presencia de instrucciones que permiten variar el flujo de control, lo cual se realiza con
instrucciones de salto o bifurcación.
Hay instrucciones de salto incondicional, que simplemente tienen un código de operación y un operando que indica la
dirección de la siguiente instrucción a ejecutar. Pero en muchas ocasiones, los saltos se realizan solamente si se da
una determinada circunstancia, es decir, necesitamos saltos condicionales.
Los saltos condicionales se realizan en función de los bits o flags de estado del registro de estado. Estos bits los
establecen muchas operaciones de transferencia de datos, lógicas y aritméticas. Además se dispone también de
operaciones de comparación, que toman dos operandos y establecen los bits de estado dependiendo de la
comparación de los dos operandos. También hay instrucciones de prueba o test, que establecen los flags de estado
considerando solamente el valor de un único operando (positivo, negativo, cero).
Algunos de los flags más comunes que suele tener el registro de estado son los que indican: overflow, acarreo, cero,
negativo.
Como resumen, decir que los saltos condicionales están formados por pares de instrucciones, una que establece el
estado, y otra que establece la condición y el salto; si el estado cumple la condición, se produce el salto. Las
instrucciones más habituales para establecer el estado son las aritméticas, las de comparación y las de prueba o test.

Hay otros mecanismos para romper el flujo secuencial de ejecución, como son las corrutinas, las interrupciones y las
excepciones (o interrupciones software). De éstas, en esta asignatura vamos a tratar solamente las interrupciones,
pero lo haremos en el capítulo dedicado a los Sistemas de Entrada/Salida

Arquitectura de Computadores Lenguaje Máquina - 23


Instrucciones Típicas …Transferencia de Control

EJEMPLO Programa que resta el valor 5 a los


contenidos de las posiciones de
memoria comprendidas entre la
$0100 y la $0200.

Dir. Instrucción
$5000 MOVE #$0100,R2 R2 Apunta a la 1ª dir.
$5004 SUB #5,(R2) Resta 5 a la pos. de memoria
. . . ADD #1,R2 Incrementa puntero
. . . CMP #0201,R2 ¿R2 en la última dirección?
. . . BNE $5004 Si no era la última, repite

Arquitectura de Computadores Lenguaje Máquina - 24

En el fragmento de programa de arriba se muestra un ejemplo en el que se utilizan instrucciones


de bifurcación condicional para controlar la repetición del bucle en el que se van incrementando las
posiciones de memoria entre la dirección $100 y la dirección $200.

Arquitectura de Computadores Lenguaje Máquina - 24


Instrucciones Típicas …Llamadas a Procedimientos
P. Pr. Proc 1 Proc 2
L Programa
Llamada CAL Dir
Proc. P1 Proc. P2
.
principal
del p.p. 4000 4500 4800

RE
TU 4100 Call P1 4600 Call P2
RN 4101 4601
Return
LL

4650 Call P2
CA

4651

Return
URN
T
RE

4601 4651
Retorno 4101 4101 4101 4101 4101
al p.p.

Pila Después Después Después Después Después Después


inicial Call P1 Call P2 Return Call P2 Return Return
a P1 a P1 a P.P.
Arquitectura de Computadores Lenguaje Máquina - 25

Los procedimientos se utilizan asiduamente en los lenguajes de alto nivel, por lo que el lenguaje máquina debe
proporcionar un soporte para que se ejecuten eficazmente. Así, veremos aquí el mecanismo que generalmente se
utiliza para realizar las llamadas a procedimientos con el nivel que ofrece el lenguaje máquina.
Sabemos que un procedimiento o subrutina es un grupo de instrucciones que realizan alguna tarea y que puede ser
llamado desde diversos puntos de un programa. A diferencia de los saltos, estas llamadas tienen la particularidad de
que una vez terminado el trabajo del procedimiento, se devuelve el control a la siguiente instrucción del punto de
llamada. Por esto, una de las primeras cosas que hay que hacer en una llamada a procedimiento es guardar la
dirección de retorno en alguna parte. Veamos algunas posibilidades.
En un registro. Cuando se llama a un procedimiento se guarda siempre la dirección de retorno en un registro
preestablecido, así cuando finaliza el procedimiento simplemente hay que tomar la dirección de retorno de ese registro.
La pega que tiene es que si desde un programa principal se llama a un procedimiento P_1, y éste llama a su vez al
procedimiento P_2, al realizar la segunda llamada se machaca la dirección de retorno de la primera llamada.
Este problema se produce porque se utiliza el mismo lugar para guardar la dirección de retorno de todos los
procedimientos. Por esto, una mejora podría consistir en guardar la dirección de retorno en una posición de memoria
al comienzo de cada procedimiento, de tal manera que si el programa principal llama al procedimiento P_1, se
guarda la dirección de retorno en una zona de datos al comienzo del procedimiento P_1, y cuando éste llama al
procedimiento P_2, esta dirección de retorno se guarda en la zona correspondiente del procedimiento P_2, con lo que
no se machaca la primera dirección de retorno. El problema está en que no permite los procedimientos recursivos ni
los reentrantes. (Un procedimiento es reentrante si en un momento dado puede tener activas varias instancias por
haber sido llamado desde distintos procedimientos de distintos procesos).
El mejor lugar para guardar la dirección de vuelta es la Pila. Cuando se llama a un procedimiento se mete la dirección
de retorno en la cima de la pila. (Téngase en cuenta que cada proceso tiene su propia pila de trabajo). Así, si un
procedimiento se llama recursivamente, se van guardando sus direcciones de vuelta en la pila, que simplemente va
creciendo a medida que se producen las llamadas, y empezará a decrecer según se vaya llegando al final de cada
instanciación.
Por esto, todos los procesadores de propósito general disponen de instrucciones de llamada a procedimiento (CALL)
que tienen un único parámetro, la dirección del procedimiento llamado, que automáticamente salva el CP en la pila
antes de saltar al procedimiento llamado. Obviamente, también disponen de una instrucción de fin de procedimiento
(RETURN) que saca el valor de la cima de la pila y lo pone en el CP (Contador de Programa).

Arquitectura de Computadores Lenguaje Máquina - 25


Instrucciones Típicas …Llamadas a Procedimientos
procedure Ejemplo (x, y: integer) is
a, b: integer;
begin
...
b := (x * x) - (y * y); ¡ Qué pasa
... con los parámetros ?
end Ejemplo;

0000 Dir. Ret. PP


y

Direcciones
x x ≡ (PP+2)
...
y ≡ (PP+1)
...

FFFF Pila
Arquitectura de Computadores Lenguaje Máquina - 26

Una vez que sabemos guardar la dirección de retorno, debemos ocuparnos del paso de parámetros.
Podríamos pensar en poner los parámetros en una dirección fija de memoria o en registros, pero nos
encontraríamos con los mismos problemas que para salvar la dirección de retorno. Por esto, los parámetros
también se van a poner en la pila.
Supongamos un programa que en un punto determinado realiza la siguiente llamada al procedimiento P1:
CALL P_1 (x, y).
Esta es la secuencia de acciones que deben llevarse a cabo para realizar la llamada a un procedimiento:
1. Meter en la pila el parámetro x.
2. Meter en la pila el parámetro y.
3. Meter en la pila el valor del CP.
4. Saltar a la dirección del procedimiento P1.
Una vez que toma control el procedimiento llamado, tiene en la cima de la pila la dirección de retorno,
inmediatamente debajo el parámetro y y, por último, el parámetro x. Sabiendo esto, se puede acceder a los
parámetros mediante un direccionamiento relativo al PP (Puntero de Pila): PP+1, PP+2, ...
Cuando en el procedimiento llamado se alcance la instrucción RETURN, su ejecución provocará el sacar de
la pila la dirección de retorno y ponerla en el CP, con lo que se devolverá el control al procedimiento
llamante. En éste, se deberá restaurar el estado de la pila a la misma situación que tenía antes de la
llamada al procedimiento, es decir, habrá que sacar de la pila los dos parámetros que se encuentran
situados en las dos posiciones más altas de la pila. Una vez que se haya dejado la pila en su situación
original se continúa con la ejecución de la siguiente instrucción a la de la llamada al procedimiento.
Esto funciona “aparentemente”, aunque, como veremos más adelante, hay situaciones en las que este
mecanismo no es válido y necesita algún arreglo.

Arquitectura de Computadores Lenguaje Máquina - 26


Instrucciones Típicas …Llamadas a Procedimientos

¡ ... y las variables locales ?

0000
b PP
a x ≡ (PP+4)
Dir. Ret.
y ≡ (PP+3)
y
x a ≡ (PP+1)
... b ≡ (PP)
...
FFFF
Direcciones Pila

Arquitectura de Computadores Lenguaje Máquina - 27

El último aspecto que nos queda por ver de la llamada a procedimientos es la asignación de
espacio para las variables locales.
Las variables globales de un programa pueden guardarse o ubicarse en alguna zona fija de
memoria, sin embargo, no puede hacerse lo mismo con las variables locales de un procedimiento,
pues como ya hemos visto antes, se machacarían estos valores en procedimientos reentrantes o
recursivos. Por lo tanto, las variables locales de un procedimiento deben guardarse también en la
pila.
Hasta ahora hemos visto que la llamada a un procedimiento deja en la pila los parámetros y la
dirección de retorno antes de ceder el control al procedimiento llamado. Ahora, una vez que toma
control el procedimiento debe ocuparse de asignar espacio para sus variables locales. Si cada
variable necesita una palabra de memoria, lo que se puede hacer es dejar tantos huecos en la pila
como variables haya, haciendo corresponder cada hueco a una variable.
En este momento, después de haber reservado espacio para las variables locales, el escenario de
la pila será el siguiente: el PP estará apuntando a la última de las variables locales, seguida del
resto de las variables locales, en orden inverso al de su declaración. En nuestro ejemplo, el PP
estará apuntando a la variable b y PP+1 estará apuntando a la variable a; PP+2 apuntará a la
dirección de retorno, mientras que PP+3 apuntará al parámetro y y PP+4 al parámetro x.
El conjunto de valores constituido por los parámetros, la dirección de retorno y las variables locales
se denomina trama de pila.

Arquitectura de Computadores Lenguaje Máquina - 27


Instrucciones Típicas …Llamadas a Procedimientos

¡ ... y las variables temporales ?

y*y PP
x*x
0000
b x ≡ (BL+2)
a y ≡ (BL+1)
Dir. Ret. BL
y
a ≡ (BL-1)
x b ≡ (BL-2)
...
...
FFFF
Direcciones Pila

Arquitectura de Computadores Lenguaje Máquina - 28

Acabamos de ver el mecanismo para referenciar las variables locales de cada rutina. No obstante,
todavía se pueden presentar problemas. Por ejemplo, supongamos una llamada al procedimiento
de la transparencia, en el que se debe calcular la siguiente expresión
b:=(x * x)-(y * y)
Es común que la evaluación de esta expresión se realice por partes, de tal manera que primero se
calcula el valor de x2 y se guarda en la pila, a continuación se calcula el valor de y2 y también se
guarda en la pila. Por último se toman los dos valores de la cima de la pila y se restan.
Pues bien, cuando se ha metido en la pila el valor de x2 y vamos a acceder al parámetro y ¡resulta
que ya no está en PP+3! Esto es porque la pila ha crecido, la cima de la pila se ha desplazado y
por lo tanto el registro PP ha variado su valor.
Para evitar este problema lo que se necesita es un registro que esté continuamente apuntando a la
trama de la pila en curso (puede haber otras tramas debajo si hay llamadas anidadas). A este
registro lo vamos a llamar BL (Base Local). Así, lo primero que debe hacer el procedimiento
llamado es poner el BL con el valor de PP actual y después reservar el espacio para sus variables
locales. Así, posteriormente podrá direccionar los parámetros y las variables locales mediante
direccionamiento relativo al BL (BL-1, BL-2, ...), con lo que ya no importa que el PP varíe su
valor debido a variables temporales.

Arquitectura de Computadores Lenguaje Máquina - 28


Instrucciones Típicas …Llamadas a Procedimientos
¡ ... y que pasa con el BL de las tramas anteriores ?
b PP
0000 a
BL de P2 BL (de P3)
Dir. Ret. x ≡ (BL+3)
y y ≡ (BL+2)
x
... a ≡ (BL-1)
... b ≡ (BL-2)
q
FFFF BL de P1
Direcciones … y permite acceder a las variables
¡ !
Dir. Ret.
p locales de las rutinas llamantes
...

Arquitectura de Computadores Lenguaje Máquina - 29

Todavía nos queda un problema por resolver. Supongamos que desde un procedimiento P1 se llama a un
procedimiento P2, y que éste llama a su vez al procedimiento P3. Mientras se está ejecutando P2, el registro BL está
apuntando a la trama de pila de P2, pero cuando éste llama a P3 el BL se actualiza con la dirección de la trama de pila
de P3, machacando ¡y perdiendo! la dirección de la trama de pila de P2. Es decir, cuando se llama a un procedimiento
se pierde la dirección de la trama de pila del procedimiento llamante.
La forma de solucionar esto es muy simple, consiste en guardar en cada trama de pila la dirección de la trama de pila
del proceso llamante antes de actualizar el BL con la dirección de la nueva trama de pila.
Veamos cual sería el orden completo de las acciones de una llamada:
• Secuencia de llamada (en el procedimiento llamante):
1. Meter los parámetros en la pila.
2. Meter en la pila la dirección de retorno.
3. Ceder el control al procedimiento llamado.
• Prólogo del procedimiento llamado:
4. Guardar en la pila el valor del registro BL.
5. Copiar el registro PP al registro BL.
6. Asignar espacio en la pila para las variables locales (moviendo el PP).

Por su parte, esto es lo que origina la terminación de un procedimiento:


• Epílogo de la rutina llamada:
1. Liberar el espacio de las variables locales: BL → PP
2. Restaurar el anterior BL, sacándolo de la pila.
3. Retorno al procedimiento llamante, sacando la dirección de retorno de la pila.
• Secuencia de retorno del procedimiento llamante:
4. Liberar el espacio de pila utilizado para los parámetros (moviendo el PP).

Los procesadores suelen ofrecer instrucciones para ejecutar fácilmente el prólogo y el epílogo de los procedimientos
(Intel: ENTER y LEAVE; Motorola: LINK y UNLK). Las máquinas RISC como PowerPC no disponen de este tipo de
instrucciones.
La instrucción ENTER del Pentium consume 11 ciclos de reloj para su ejecución, aunque si el prólogo se realiza a base
de instrucciones elementales requiere solamente 1,5 ciclos ¡!

Arquitectura de Computadores Lenguaje Máquina - 29


Lenguaje Máquina …Instrucciones Típicas

¡ Y la Entrada/Salida ?
¿Cómo se leen y escriben
los datos?

Arquitectura de Computadores Lenguaje Máquina - 30

¡Y cómo se realiza la entrada/salida?


Por supuesto que faltan los mecanismos de E/S, pero es que sobre esto hay mucho que hablar, y
lo veremos con detalle en el capítulo dedicado a los Sistemas de Entrada/Salida.

Arquitectura de Computadores Lenguaje Máquina - 30

También podría gustarte