Está en la página 1de 7

PILA (STACK)

La pila es una característica interna del 8086/8088. Proporciona a los programas un lugar donde almacenar y seguir la pista del
trabajo que se está llevando a cabo. La función más importante de la pila es la de mantener el registro de los lugares donde se
llamó a una subrutina y de los parámetros que se le pasaron. La pila también puede utilizarse para el almacenamiento temporal
de datos de trabajo, aunque esto es menos fundamental y no tan común.La pila obtiene su nombre por analogía con los
montones de platos apilados (pilas de platos). Cuando un dato nuevo es introducido (push) en la cima de la pila, éste será el
primer en ser extraído (pop). Por eso se dice que la pila siempre opera en el orden “último en entrar, primero en salir” (LIFO,
Last In First Out). Esto significa que cuando la pila se utiliza para seguir la pista de los retornos de las subrutinas, la primera
llamada a subrutina que se hizo es la última que vuelve. De esta manera, la pila mantiene ordenado el funcionamiento del
programa, las subrutinas y las rutinas de tratamiento de interrupción, sin importar lo complejo de la operación. La pila se utiliza
desde la parte de abajo (dirección más alta) a la parte de arriba (dirección más baja), de forma que cuando un dato es
introducido (push) a la cima de la pila, se almacena en la posición de memoria justo por debajo de la cima actual. Así, la pila
crece hacia abajo de forma que, a medida que se añaden datos, la posición de la cima se mueve más y más hacia direcciones
más bajas, decrementando cada vez el valor de SP.

Cualquier parte de un programa puede crear un nuevo espacio de pila en el momento que desee. Por lo general, cuando un
programa está funcionando se crea para él una sola pila y se utiliza durante todo el funcionamiento. No hay una forma sencilla
de estimar el tamaño de la pila que un programa pueda necesitar, y el diseño del 8086/8088 no proporciona ninguna manera
automática de detectar cuándo el espacio de pila está agotado o casi agotado. Esto puede llevar a que los programadores estén
indecisos acerca del espacio que deben reservar para la pila. Una estimación conservadora del espacio que hay que reservar
da alrededor de 2 KB (2048 bytes), que es la cantidad que asignan por defecto la mayoría de los compiladores de lenguajes de
alto nivel.

.CODE
Inicio: ;Punto de entrada al programa
Mov AX,5 ;AX=5
Mov BX,10 ;BX=10
Push AX ;Pila=5
Mov AX,BX ;AX=10
Pop BX ;BX=5
Mov AX,4C00h ;Terminar programa y salir al DOS
Int 21h ;
END Inicio
END

PROCEDIMIENTOS
Uso de un procedimiento
Los procedimientos son un conjunto de instrucciones que se pueden ejecutar desde muchos
lugares diferentes de un programa, en vez de tener que repetir muchas veces el mismo
conjunto de instrucciones cada vez que se necesitan
Los procedimientos se llaman mediante la instrucción CALL
La última instrucción de un procedimiento es la instrucción RET
La dirección de retorno de un procedimiento (y en ciertos casos, procedimiento tipo FAR, el
segmento al que pertenece) se almacena en la pila
Para delimitar el conjunto de instrucciones que forman un procedimiento se emplean las
palabras clave: PROC (comienzo del procedimiento) y ENDP (final del procedimiento)
Un procedimiento se declara de la siguiente manera:
nombreProc PROC [near/far]
Instrucciones a ejecutar
[ret]
nombre ENDP
Las directivas PROC y ENDP indican el inicio y el fin del procedimiento, nombreProc indica el nombre del procedimiento, debe
ser único y no debe tener el nombre de una directiva o palabra reservada.
Near/far depende si la operación implica un procedimiento cercano o lejano.
La instrucción ret regresa al segmento donde fue invocado el procedimiento.
La llamada a un procedimiento se hace mediante call nombreProc.
Ejemplo de un procedimiento que imprime un mensaje:
.model small
.stack 64
.data
msj db 0ah,0dh, 'Mi primer procedimiento','$'
msj2 db 0ah,0dh, 'miensamblador.blogspot','$'
.code
inicio:
call imprime ;Llamada al procedimiento imprime
call imprime2

Salir: ;Etiqueta para salir del programa


mov ah,04ch
int 21h

imprime proc near ;Declaración de el procedimiento imprime, imprime un mensaje


mov ax,@data
mov ds,ax
mov ah,09h
mov dx,offset msj
int 21h
ret ;regresamos el procedimiento de donde lo llamaron.
imprime endp

imprime2 proc near


mov ax,@data
mov ds,ax
mov ah,09h
mov dx,offset msj2
int 21h
ret
imprime2 endp

end
Nombre: CLI
Formato: CLI
Descripción:
Desactiva las interrupciones
Las interrupciones no enmascarables no se pueden inhibir
Ejemplos:
CLI
Nombre: STI
Formato: STI
Descripción:
Permite las interrupciones
Ejemplos:
STI

Nombre: CLC
Formato: CLC
Descripción:
Desactiva el flag de acarreo
Ejemplos:
CLC
Nombre: STC
Formato: STC
Descripción:
Activa el flag de acarreo
Ejemplos:
STC

Nombre: CLD
Formato: CLD
Descripción:
Pone a cero el flag de dirección (para trabajar con las instrucciones de cadenas)
Ejemplos:
CLD
Nombre: STD
Formato: STD
Descripción:
Pone a uno el flag de dirección (para trabajar con las instrucciones de cadenas)
Ejemplos:
STD

Segmentos simplificados
Permite definir los segmentos sin necesidad de utilizar las directivas de segmentos que aparecen más arriba.

.MODEL modelo: Debe estar ubicada antes de otra directiva de segmento. El modelo puede ser uno de los siguientes:
TINY: Los datos y el código juntos ocupan menos de 64 KB por lo que entran en el mismo segmento. Se utiliza para programas
.COM. Algunos ensambladores no soportan este modelo.
SMALL: Los datos caben en un segmento de 64 KB y el código cabe en otro segmento de 64 KB. Por lo tanto todo el código y
los datos se pueden acceder como NEAR.
MEDIUM: Los datos entran en un sólo segmento de 64 KB, pero el código puede ser mayor de 64 KB. Por lo tanto, código es
FAR, mientras que los datos se acceden como NEAR.
COMPACT: Todo el código entra en un segmento de 64 KB, pero los datos no (pero no pueden haber matrices de más de 64
KB). Por lo tanto, código es NEAR, mientras que los datos se acceden como FAR.
LARGE: Tanto el código como los datos pueden ocupar más de 64 KB (pero no pueden haber matrices de más de 64 KB), por
lo que ambos se acceden como FAR.
HUGE: Tanto el código como los datos pueden ocupar más de 64 KB (y las matrices también), por lo que ambos se acceden
como FAR y los punteros a los elementos de las matrices también son FAR.
.STACK [size]: Define el segmento de pila de la longitud especificada.
.CODE [name]: Define el segmento de código.

.DATA: Define un segmento de datos NEAR con valores iniciales.

.DATA?: Define un segmento de datos NEAR sin valores iniciales.

.FARDATA [name]: Define un segmento de datos FAR con valores iniciales.

.FARDATA? [name]: Define un segmento de datos FAR sin valores iniciales.

.CONST: Sefine un segmento de datos constantes.

Los siguientes símbolos están definidos cuando se usan las directivas anteriores:

@curseg: Tiene el nombre del segmento que se está ensamblando.


@filename: Representa el nombre del archivo fuente (sin la extensión)
@codesize: Vale 0 para los modelos SMALL y COMPACT (código NEAR), y vale 1 para los modelos MEDIUM, LARGE y HUGE
(código FAR).
@datasize: Vale 0 para los modelos SMALL y MEDIUM (datos NEAR), vale 1 para los modelos COMPACT y LARGE (datos FAR)
y vale 2 para el modelo HUGE (punteros a matrices FAR).
@code: Nombre del segmento definido con la directiva .CODE.
@data: Nombre del segmento definido con la directivas .DATA, .DATA?, .CONST y .STACK (los cuatro están en el mismo
segmento).
@fardata: Nombre del segmento definido con la directiva .FARDATA.
@fardata?: Nombre del segmento definido con la directiva .FARDATA?.

SUBRUTINAS:
Declaración:
<nombre la de subrutina> PROC
<instrucciones de la subrutina>
RET
<nombre de la subrutina> ENDP
Llamada:
CALL <nombre de la subrutina>
INTERRUPCIONES:
Definición de interrupción:
Una interrupción es una instrucción que detiene la ejecución de un programa para permitir el uso de la UCP a un proceso
prioritario. Una vez concluido este último proceso se devuelve el control a la aplicación anterior. Por ejemplo, cuando estamos
trabajando con un procesador de palabras y en ese momento llega un aviso de uno de los puertos de comunicaciones, se
detiene temporalmente la aplicación que estábamos utilizando para permitir el uso del procesador al manejo de la información
que está legando en ese momento. Una vez terminada la transferencia de información se reanudan las funciones normales del
procesador de palabras. Las interrupciones ocurren muy seguido, sencillamente la interrupción que actualiza la hora del día
ocurre aproximadamente 18 veces por segundo. Para lograr administrar todas estas interrupciones, la computadora cuenta
con un espacio de memoria, llamado memoria baja, donde se almacenan las direcciones de cierta localidad de memoria donde
se encuentran un juego de instrucciones que la UCP ejecutará para después regresar a la aplicación en proceso. La sentencia
para usar una interrupción en ensamblador es INT número. En el programa anterior hicimos uso de la interrupción número
21h para llamar a DOS. A continuación describiremos los 3 tipos de interrupciones:
1) INTERRUPCIONES INTERNAS DE HARDWARE:
Las interrupciones internas son generadas por ciertos eventos que surgen durante la ejecución de un programa. Este tipo de
interrupciones son manejadas en su totalidad por el hardware y no es posible modificarlas. Un ejemplo claro de este tipo de
interrupciones es la que actualiza el contador del reloj interno de la computadora, el hardware hace el llamado a esta
interrupción varias veces durante un segundo para mantener la hora actualizada. Aunque no podemos manejar directamente
esta interrupción (no podemos controlar por software las actualizaciones del reloj), es posible utilizar sus efectos en la
computadora para nuestro beneficio, por ejemplo para crear un "reloj virtual" actualizado continuamente gracias al contador
del reloj interno. Unicamente debemos escribir un programa que lea el valor actual del contador y lo traduzca a un formato
entendible para el usuario.
2) INTERRUPCIONES EXTERNAS DE HARDWARE:
Las interrupciones externas las generan los dispositivos periféricos, como pueden ser: teclado, impresoras, tarjetas de
comunicaciones, etc. También son generadas por los coprocesadores. No es posible desactivar a las interrupciones externas.
Estas interrupciones no son enviadas directamente a la UCP, sino que se mandan a un circuito integrado cuya función es
exclusivamente manejar este tipo de interrupciones. El circuito, llamado PIC 8259A, si es controlado por la UCP utilizando para
tal control una serie de vías de comunicación llamadas puertos.
3) INTERRUPCIONES DE SOFTWARE:
Las interrupciones de software pueden ser activadas directamente por el ensamblador invocando al número de interrupción
deseada con la instrucción INT. El uso de las interrupciones nos ayuda en la creación de programas, utilizándolas nuestros
programas son más cortos, es más fácil entenderlos y usualmente tienen un mejor desempeño debido en gran parte a su menor
tamaño. Este tipo de interrupciones podemos separarlas en dos categorías: las interrupciones del sistema operativo DOS y las
interrupciones del BIOS. La diferencia entre ambas es que las interrupciones del sistema operativo son más fáciles de usar pero
también son más lentas ya que estas interrupciones hacen uso del BIOS para lograr su cometido, en cambio las interrupciones
del BIOS son mucho más rápidas pero tienen la desventaja que, como son parte del hardware son muy específicas y pueden
variar dependiendo incluso de la marca del fabricante del circuito

La elección
del tipo de interrupción a utilizar dependerá únicamente de las características que le quiera dar a su
programa: velocidad (utilizando las del BIOS) o portabilidad (utilizando las del DOS).
Interrupción 21H
Propósito: Llamar a diversas funciones del DOS.
Sintaxis:
Int 21H
Nota: Cuando trabajamos en TASM es necesario especificar que el valor que estamos utilizando es
hexadecimal. Esta interrupción tiene varias funciones, para acceder a cada una de ellas es necesario
que el registro AH se encuentre el número de función que se requiera al momento de llamar a la
interrupción.

SALTOS, CICLOS Y PROCEDIEMIENTOS:


Los saltos incondicionales en un programa escrito en lenguaje ensamblador están dados por la instrucción JMP, un salto es
alterar el flujo de la ejecución de un programa enviando el control a la dirección indicada. Un ciclo, conocido también como
iteración o bucle, es la repetición de un proceso un cierto número de veces hasta que alguna condición se cumpla. En estos
ciclos se utilizan los bifurcaciones "condicionales" basados en el estado de las banderas. Por ejemplo la instrucción JNZ
que salta solamente si el resultado de una operación es diferente de cero y la instrucción JZ que salta si el resultado de la
operación es cero. Por último tenemos los procedimientos o rutinas, que son una serie de pasos que se usarán repetidamente
en el programa y en lugar de escribir todo el conjunto de pasos únicamente se les llama por medio de la instrucción CALL. Un
procedimiento en ensamblador es aquel que inicie con la palabra PROC y termine con la palabra RET (ya explicado
anteriormente). Realmente lo que sucede con el uso de la instrucción call es que se guarda en la pila el registro IP y se carga la
dirección del procedimiento en el mismo registro, conociendo que IP contiene la localización de la siguiente instrucción que
ejecutara la UCP, entonces podemos darnos cuenta que se desvía el flujo del programa hacia la dirección especificada en este
registro. Al momento en que se llega a la palabra RET se saca de la pila el valor de IP con lo que se devuelve el control al punto
del programa donde se invocó al procedimiento. Es posible llamar a un procedimiento que se encuentre ubicado en otro
segmento, para ésto el contenido de CS (que nos indica que segmento se está utilizando) es empujado también en la pila.

. Stack o pila
Stack o pila es una estructura de datos con acceso del tipo LIFO (Last In First Out), último en entrar, primero en salir. Como
similitud se puede asociar a un almacenamiento de libros formando una pila, en la que se almacenan uno sobre otro, los nuevos
elementos se apilan sobre el último, y cunado se retiran se extrae el último que se ha apilado.

Este tipo de estructura de datos es fácil de desarrollar por los sistemas microprocesadores y resulta de gran utilidad para
trabajar con listas de datos y es imprescindible para el trabajo interno del microprocesador en las subrutinas e interrupciones.

Algunos microprocesadores pueden tener el Stack en su interior, representando un sistema muy rápido pero de tamaño
limitado, la mayoría de microprocesadores disponen el stack en la memoria externa, hecho que proporciona una gran
capacidad de almacenamiento y el control de su ubicación, aunque el acceso sea más lento.

5.3.1. Puntero de la pila (stack pointer)


El puntero del stack SP (stack pointer) como su propio nombre indica es un registro apuntador a la posición de memoria donde
se encuentra la pila. En la familia 8051 el registro SP se encuentra en la zona de memoria SFR 81H.

También podría gustarte