Está en la página 1de 26

Subrutinas

La unidad de descomposicin modular bsica se conoce como


subrutina. Una subrutina (tambin conocida como funcin,
mtodo, procedimiento o subprograma, dependiendo del
lenguaje de programacin) es una porcin de cdigo dentro
de un programa ms grande, que realiza una tarea especfica
y es relativamente independiente del resto del cdigo.
Un ejemplo: Supongamos que tenemos un programa que
administra las notas de alumnos en un colegio secundario. En
el programa se cargan las notas de todas las materias, mes a
mes, y el programa puede calcular el promedio del alumno en
cada materia, en cada trimestre y el promedio general de
todo el curso. Como vemos, este programa deber calcular
gran cantidad de promedios. Pero el algoritmo para calcular
un promedio es siempre el mismo. Tenemos entonces un
candidato claro para una subrutina.
Creamos una subrutina que calcule un promedio y luego la
podemos utilizar cuantas veces queramos. Si detectramos
que existe un problema en el clculo del promedio, sabemos
que debemos buscarlo dentro de esa subrutina.
Para que el programa principal de nuestro sistema de alumnos
sepa cmo interactuar con la subrutina Promedio lo que
necesita es conocer su interfaz. La interfaz de una subrutina
indica de qu forma la subrutina recibe una entrada de datos
y de qu forma produce una salida. Por ejemplo, la subrutina
Promedio, deber recibir una coleccin de nmeros y deber
retornar el promedio (otro nmero).
Una subrutina en un lenguaje de alto nivel que calcule un
promedio podra ser como sigue. Por simplicidad, vamos a
hacer una subrutina que calcula el promedio de 2 nmeros
(en lugar de una ms general, que sera lo lgico, que calcule
el promedio de n nmeros)

Bsicamente, esta definicin nos est diciendo que la funcin


Promedio recibe dos valores de tipo real y devuelve otro valor
real. El comando Return hace que se realice el clculo y se
devuelva el resultado. Esto es similar a la definicin de una
funcin en matemtica (de ah la palabra clave Function).
En cualquier lugar del cdigo del programa, podramos
calcular un promedio entre dos nmeros con una instruccin
similar a esta:
Al ejecutar este cdigo, la variable Resultado terminar
teniendo el valor 5.5 (el promedio entre 8 y 3).
Fjense que este cdigo para poder utilizar la subrutina slo
debe conocer su interfaz, es decir: debe saber cmo se llama
la subrutina, qu tipo de valores darle como entrada (son los
que van entre parntesis) y qu tipo de valor esperar como
salida (lo que queda asignado en Resultado en el ejemplo).
La interfaz de la subrutina est formada por:
El nombre de la subrutina.
Los parmetros: los valores de entrada sobre los que la
subrutina opera (en el caso anterior a y b, dos nmeros
reales). Una subrutina puede recibir ninguno, uno o ms
parmetros.
El valor de retorno: es el valor que la subrutina devuelve,
como en el ejemplo anterior. Hay subrutinas que no devuelven
un valor, sino que realizan una tarea (por ejemplo: una
subrutina que muestra un mensaje en pantalla).
Una descripcin de qu hace la subrutina. En una subrutina
tan simple como la anterior, la funcionalidad de la subrutina
puede inferirse del nombre, pero subrutinas ms complejas
pueden requerir una aclaracin especial

Es claro que con slo conocer la interfaz basta para poder


usar la subrutina.
En el ejemplo anterior, la interfaz sera: esta subrutina recibe
dos parmetros a y b de tipo real y retorna el promedio entre
ambos. El programa no necesita saber cmo realiza el
clculo. Por eso se dice que las subrutinas son como cajas
negras. Es decir, al utilizarlas, no necesitamos saber qu es lo
que ocurre en el cdigo interno de la subrutina, slo nos
interesa qu valores pasarle y qu nos devuelve.
Esto tiene la ventaja de que, una vez establecida la interfaz, el
programa principal y la subrutina pueden ser desarrollados
independientemente, en paralelo, e incluso por personas
distintas. (En un ejemplo tan simple como el clculo de un
promedio esto puede parecer intil, pero volvamos a un
ejemplo del mundo real: S es til que las subrutinas que se
encargan de la correccin ortogrfica en Word puedan
desarrollarse en forma paralela e independientemente de
aquellas que permiten dar formato al texto. Pensemos que
ambas funcionalidades son totalmente independientes y
bastante complejas en s mismas).
Subrutinas en Assembler.
Cmo hacen los programas que utilizan subrutinas para
trabajar de la forma en que lo hacen? El programa principal
llama a una subrutina y queda dormido hasta que la subrutina
termine. Cmo se logra esto?
Repasemos cmo trabaja el procesador para ejecutar un
programa:
1) Busca en el segmento de cdigo (CS) la instruccin ubicada
en la direccin indicada por el registro IP.
2) Se decodifica y ejecuta la instruccin.

3) IP se incrementa para encontrar la siguiente instruccin Y


esto se repite continuamente
Qu pasara si en el paso 2 la instruccin alterara el
contenido del registro IP? Al incrementar IP para buscar la
prxima instruccin, el procesador saltara a otra rea de
cdigo.
Esto es lo que pasa siempre que utilizamos una instruccin de
salto (JMP, JNE, JZ, JGE, etc.). Por ejemplo, JNE se fija si la
comparacin anterior dio distinto y, si es as, cambia el
contenido del IP para que el procesador salte a otra lnea.
Entonces, podramos pensar que una subrutina se implementa
simplemente como un salto... Pero hay un problema: el salto
sabe ir pero no volver. Es decir, con el salto voy a donde
comienza la subrutina, pero despus, desde la subrutina,
cmo s a qu punto del programa principal volver?
(Recuerden que una subrutina puede ser llamada muchas
veces en distintos puntos del programa, incluso desde otras
subrutinas).
Para resolver este problema, el procesador cuenta con dos
instrucciones especiales CALL (llamada a subrutina) y RET
(retorno de subrutina). Ambas instrucciones hacen uso de un
rea especial de memoria llamada pila (o stack, por su
nombre en ingls).

Pilas.
Una pila es una estructura de datos de tipo LIFO (Last In First
Out, el ltimo en entrar es el primero en salir) que permite
almacenar y recuperar datos usando dos operaciones: PUSH
(apilar) y POP (desapilar).

Esta estructura de datos funciona como si fuera una pila de


platos: cuando apilo un plato slo puedo hacerlo en el tope de
la pila y para quitar un plato slo puedo hacerlo desde el tope
de la pila.
Una pila bien definida no permite acceder a otro elemento que
no sea el que se encuentre en el tope; slo una vez que haya
quitado el elemento del tope, puedo sacar el que estaba
inmediatamente debajo (y ningn otro ms hasta que no quite
ste, y as sucesivamente).

Los sistemas con arquitectura Intel, como los que hemos


visto, implementan una estructura de pila que el programa
puede utilizar como un rea para almacenar datos
temporalmente.
Para esto se tiene: un segmento de pila (otra rea similar a los
segmentos de datos y de cdigo). La direccin de este
segmento est indicada por el registro SS.
Un puntero de pila, que es el registro SP. Este registro indica la
direccin del dato que se encuentra en el tope de la pila.
Las instrucciones PUSH y POP, que funcionan como vimos
recin.
Como restriccin, todos los elementos que apilemos deben ser
de 16 bits.

La pila funciona de la siguiente manera:


La pila funciona de la siguiente manera:
Subrutinas y la pila.
Pero, qu tiene que ver la pila con las subrutinas?

Como dijimos, si estamos ejecutando un cdigo y saltamos a


otro punto (al comienzo de la subrutina) tenemos el problema
de que no sabemos a dnde volver luego de ejecutar la
subrutina. Para poder volver necesitaramos restaurar el valor
que el registro IP tena antes de saltar a la subrutina.
Las instrucciones CALL y RET resuelven este problema
haciendo uso de la pila. Cuando se realiza una llamada a una
subrutina con CALL, esta instruccin automticamente guarda
el contenido del registro IP en la pila y salta al comienzo de la
subrutina. En algn punto de la subrutina el procesador se
encontrar con la instruccin RET que, al ejecutarla,
desapilar el valor del IP guardado en la pila de modo que
cuando el procesador avance a la siguiente instruccin
(incremente IP), estar de vuelta en la instruccin siguiente a
donde se hizo la llamada.

Ojo! Hay que asegurarse de que al ejecutar la instruccin


RET, el dato que se encuentra en el tope de la pila sea la
direccin IP de retorno, de lo contrario se desapilar un valor
incorrecto y el procesador ir a ejecutar instrucciones a otra
rea de memoria (lo que terminar, probablemente, con que
el programa se cuelgue). Entonces, siempre que una
subrutina apile datos (PUSH) debe recordar desapilarlos (POP).
Si lo pensamos, nos daremos cuenta de que este mecanismo
nos permite con igual facilidad ir del programa principal a una
subrutina como de una subrutina a otra. De hecho, se pueden
anidar las llamadas a subrutinas, es decir tener un
programa que llama a una subrutina, que llama a otra
subrutina, que llama a otra, etc... Lo que suceder en ese
caso es que se apilarn sucesivamente varios valores de IP.
Por el mecanismo de la pila, el ltimo IP en entrar en la pila
ser el primero en desapilarse, de modo que esto nos
permitir volver de una subrutina al cdigo que nos llam sin
problemas:

Formato de un programa con subrutinas.


Salvar el estado.
La pila puede ser utilizada dentro de una subrutina para salvar
el estado de los registros que vamos a modificar. Por ejemplo,
supongamos que en la subrutina vamos a utilizar CX para un
LOOP, qu pasa si esta subrutina fue llamada desde dentro
de un LOOP en el programa principal? Tanto la subrutina como
el programa estn alterando el valor de CX. Cuando la
subrutina termine el LOOP, CX va a valer 0. Cuando la
subrutina vuelva, el LOOP del programa principal va a ver un 0
en CX y va a terminar, pero slo realiz una iteracin... Esto
sucedi porque perdi el valor de CX que iba contando la
cantidad de vueltas que faltaban.
Esto se resuelve fcilmente utilizando el mismo mecanismo
que usan CALL y RET para salvar y recuperar el IP: Al principio
de la subrutina, guardamos en la pila el valor de los registros
que vamos a escribir y, antes del RET, desapilamos todos los
registros para recuperar su valor original. De esta forma, el
valor que tuvieran en el programa principal se conserva y el
programa no se entera de que hubo una modificacin.
Atencin: al desapilar los registros salvados, hay que hacerlo
en orden inverso a como se los apil. Recordar que en la pila
lo ltimo que se apil es lo primero que se desapila.
Pasaje de parmetros.
En Assembler podemos utilizar dos mecanismos para
comunicarnos con una subrutina:
Los registros
La pila
Pasaje de parmetros en registros.
La idea es simple: el programa principal escribe los datos a
pasar a la subrutina en uno o varios registros.

Luego, la subrutina lee esos mismos registros para obtener los


datos. A su vez, la subrutina puede devolver datos al
programa principal utilizando el mismo mecanismo.
Una vez ms, lo ms importante en este caso es que el
programa principal y la subrutina respeten una misma
interfaz.
Veamos un ejemplo: la interfaz de una subrutina que devuelva
el mayor de dos nmeros podra ser: recibe los nmeros en AX
y BX y devuelve el mayor entre ambos en AX. Entonces, el
invocador deber asegurarse de copiar en AX y BX los valores
antes de llamar a la subrutina. Cuando la subrutina arranca
supone que AX y BX tienen cargados los nmeros.

Pasaje de parmetros en la pila.


Para pasar parmetros en la pila, se apilan los datos (PUSH)
antes de invocar a la subrutina. La subrutina leer los datos
desde la pila y operar sobre ellos. Se puede utilizar la pila
tanto para enviar datos a una subrutina como para recibir
datos desde sta o bien slo recibir por la pila y devolver por
registros.
Si reescribimos la subrutina anterior para que ahora utilice la
pila para recibir los datos, la nueva interfaz podra ser: la
subrutina Mayor recibe dos nmeros en la pila y devuelve en
AX el mayor de ambos
El programa principal sigue siendo el mismo, excepto en la
llamada a la subrutina. Ahora tenemos:
Ahora, veamos cmo va quedando la pila al ejecutar cada una
de estas instrucciones:

Nos encontramos en un problema: al hacer CALL, se apila la


direccin de retorno (IP actual), de modo que cuando vayamos
a la subrutina no podemos hacer POP para recuperar los
parmetros.
Para resolver este problema, lo que tendremos que hacer es
quebrantar las reglas de la estructura de datos pila: vamos a
acceder a los elementos que no estn en el tope de la pila y
sin utilizar POP. Para eso, usaremos direccionamiento relativo
al registro BP, que es el nico que nos sirve para expresar
direcciones en la pila. Recordemos que entre corchetes
(direccin de memoria) slo podemos utilizar los registros BX,
BP, SI y DI. BX, SI y DI se utilizan sobre el segmento de datos
(DS) y BP sobre el segmento de pila (SS).
De manera que toda subrutina que utilice la pila deber
comenzar con estas dos lneas:

Como vamos a modificar el registro BP, primero lo guardamos


en la pila. Esto es muy importante ya que todas las subrutinas
que reciben parmetros por la pila usan BP; tenemos que
asegurarnos de que al salir BP recupere el valor que tena.
Al ejecutar esas instrucciones, nos queda:

Ahora, para acceder a los datos podemos utilizar expresiones


como SS:[BP+4], por ejemplo, para acceder al segundo
parmetro (F53Ch). Recordemos que cada elemento de la pila
ocupa 2 bytes, o sea que si tenemos que saltear 2 elementos
para llegar al dato que necesitamos debemos sumar 4. SS:
[BP+6] nos permite acceder al primer parmetro (100Ah).
Veamos como queda ahora nuestro cdigo:
Antes de retornar debemos desapilar BP y todos los
parmetros. Esto ltimo se logra poniendo un nmero a
continuacin de la instruccin RET que indica el nmero de
bytes a desapilar adems del IP. En el ejemplo estamos
indicando que desapile 4 bytes (los dos parmetros). Esto nos
evita tener que desapilar a mano (usando PUSH) los
parmetros al volver de la subrutina.
Subrutinas recursivas.
La recursividad es una tcnica de programacin importante.
Se utiliza para realizar una llamada a una funcin desde la
misma funcin.
Un algoritmo recursivo es un algoritmo que se define en
trminos de s mismo. Una subrutina recursiva es aquella que
incluye en su cdigo una llamada a la misma subrutina.
Un clsico ejemplo humorstico de un texto recursivo que
parodia las definiciones de los diccionarios es:
Recursividad: Vase Recursividad.

Sin embargo, este texto es un ejemplo de una definicin


recursiva errnea. El error est en que no existe una condicin
de finalizacin, lo que lleva a una recursividad infinita. Para
entender la recursividad, hay que darse cuenta de que la
clave est en la condicin de finalizacin. Una versin ms
correcta de la definicin anterior podra ser:
Recursividad: Si an no se entiende, vase Recursividad.
Un chiste informtico dice as: Para entender la recursividad,
debes entender la recursividad.

Veamos un ejemplo de un procedimiento iterativo (no


recursivo) para calcular la suma de los nmeros naturales
entre 1 y n (obviamente hay formas muchsimo ms eficientes
de hacer esto, pero es slo un ejemplo):

O sea, lo que codificamos fue exactamente la definicin


bsica de la sumatoria de 1 a n:

Pero existe una forma recursiva de definir la misma sumatoria:

El primero es el paso recursivo: la sumatoria de i entre 1 y n


es igual a n ms la sumatoria de i entre 1 y n-1. Fjense que
usamos la sumatoria para definir a la sumatoria. Si nos
quedramos ah, tendramos una recursividad infinita, pero el
segundo punto nos da el caso base (la condicin de fin): la
suma i entre 1 y 1 es 1. Esta vez no hay recursividad.

Veamos, usando la definicin recursiva:

Aunque en este ejemplo la recursividad parezca slo una


complicacin, hay muchos algoritmos que pueden expresarse
naturalmente y de manera ms sencilla si se utiliza
recursividad. (Ejemplos de esto son recorridos de estructuras
de datos como rboles o grafos, bsquedas y algoritmos de
programacin dinmica... todos temas interesantes, pero que
exceden nuestro objetivo en este momento).
Veamos, entonces, cmo se implementa la misma funcin
Suma1aN, pero esta vez de forma recursiva, usando la
definicin de la sumatoria que acabamos de ver:
Subrutinas recursivas en Assembler.
Veamos la implementacin de la subrutina anterior utilizando
Assembler:

El mecanismo a travs del cual se logran llamadas recursivas


en Assembler es exactamente el mismo que en el de llamadas
estndar. Cada vez que hay una llamada (a la misma
subrutina en este caso) se apila el IP y al retornar se desapila.
En el caso de subrutinas recursivas, hay que tener ms
presente que nunca que cada ejecucin de la subrutina utiliza
los mismos registros. Por ejemplo, en la subrutina anterior, se
salv el valor de AX en la pila antes de volver a invocar a la
subrutina de modo de no perder el valor original.
ARREGLOS Y CADENAS.
Arreglos.
Un arreglo es una lista de variables del mismo tipo.
A diferencia de los lenguajes de alto nivel donde existen
mecanismos para declarar y usar arreglos, en ensamblador el
programador tiene que crear el cdigo para declarar y usar los
arreglos.
Declaracin de arreglos.
Para declarar arreglos se utilizan las mismas directivas
empleadas para declarar variables sencillas:
db para declarar arreglos de bytes,
dw para arreglos de palabras,
dd para arreglos de palabras dobles y
dq para arreglos de palabras cudruples.
Declaracin de arreglos.
La sintaxis de estas directivas, en el caso de declaraciones de
arreglos, son:
[nomArreg] db exp[, exp]...
[nomArreg] dw exp[, exp]...
[nomArreg] dd exp[, exp]...
[nomArreg] dq exp[, exp]...
Donde nomArreg es el nombre del arreglo y exp son
expresiones constantes. El nmero de expresiones determina

el tamao del arreglo y sus valores se utilizan para inicializar


el arreglo.
Por ejemplo:
bdtos db 0, 1, 2, 3, 4

;Arreglo de cinco
;variables de tipo byte
;inicializadas a los
;valores 0, 1, 2, 3 y 4.

cresps db 'A', 'B', 'C'


;Arreglo de tres
;variables de tipo byte
;inicializadas a los
;valores 65d, 66d y 67d.
wdtos dw 0123h, 2345h
;Arreglo de cinco
dw 4567h, 6789h ;variables de tipo
dw 89abh
;palabra inicializadas
;a ls valores 0123h, 2345h,
;4567h, 6789h y 89abh.
Declaracin de arreglos usando el operador dup.
En la declaracin de arreglos se puede utilizar el operador dup
para inicializar el arreglo a valores duplicados.
La sintaxis del operador dup es la siguiente:
Cnta dup(exp [, exp]... )
Donde cnta define el nmero de veces que el dato definido
por exp ser repetido. El operador dup aparece despus de
una directiva para declarar variables: db, dw, etc.
Se puede anidar un operador dup dentro de exp de otro dup,
hasta 17 niveles.
Declaracin de arreglos usando la directiva de repeticin rept.

La directiva de repeticin rept nos permite tambin declarar e


inicializar arreglos como se muestra en el siguiente ejemplo:

La primera lnea de la declaracin anterior utiliza la directiva


label para declarar la etiqueta bArreg de tipo byte. La
directiva label le indica al ensamblador cmo accesar a los
datos que se declaran enseguida. En este caso bArreg ser
tratado como un arreglo de bytes, no reserva espacio de
memoria.
La sintaxis de la directiva label es la siguiente:
label etiq tipo
Donde etiq es el identificador de la etiqueta y tipo es el tipo
de los datos declarados a continuacin. tipo puede ser: byte,
word, dword, etc.
Como un segundo ejemplo, se tiene la siguiente declaracin:

En este caso el smbolo val se inicializa a 0 usando la directiva


=. En cada repeticin el valor de val se ve incrementando en
uno.
Acceso a los elementos de un arreglo.
El nombre de un arreglo etiqueta la direccin donde se
encuentra el primer elemento de un arreglo. Esto es, el
nombre del arreglo es la direccin base del arreglo.

La direccin de cualquier elemento del arreglo se puede


expresar como la suma de la direccin base del arreglo ms la
distancia de ese elemento con respecto al primer elemento
del arreglo.
Esa distancia puede medirse de dos formas:
La distancia expresada en nmero de elementos, llamada
tambin ndice, o la distancia medida en bytes, llamada
tambin desplazamiento.
El primer elemento de un arreglo tiene un ndice de cero.
Tambin su desplazamiento es de cero. Si el arreglo es de
bytes el ndice y el desplazamiento son iguales.
Para los arreglos de otros tipos el desplazamiento es un
mltiplo del ndice y est dado por:
desplazamiento = tamDato * ndice
Donde tamDato es el tamao en bytes de cada elemento del
arreglo.
A diferencia de los lenguajes de alto nivel donde se accesa a
los elementos de un arreglo mediante su ndice, en
ensamblador se accesa a los elementos de un arreglo
mediante su desplazamiento.
Por ejemplo sean, las siguientes declaraciones:

Entonces, las siguientes instrucciones almacenan el valor de 5


en el primer elemento, ndice 0, y el valor de 6 en el tercer
elemento, ndice 2, de bdtosx.

Y la siguientes instrucciones almacenan el valor de 500 en el


primer elemento, ndice 0, y el valor de 300 en el cuarto
elemento, ndice 3, de wdtosx:
En muchas ocasiones deseamos accesar a los elementos de
un arreglo en una secuencia determinada por lo que sera
conveniente que el ndice o el desplazamiento de un elemento
del arreglo estuviera en una variable o en un registro. En este
caso, se puede utilizar el direccionamiento base para accesar
a los elementos del arreglo.
Por ejemplo, las siguientes instrucciones almacenan el valor
de 6 en el elemento del arreglo bdtosx cuyo ndice est en la
variable indice:

Por otro lado, las siguientes instrucciones almacenan el valor


de 300 en el elemento del arreglo wdtosx cuyo ndice est en
la variable indice:

Otros modos de direccionamiento que pueden emplearse para


accesar a los elementos de un arreglo son:
El direccionamiento indirecto,
El direccionamiento indexado y
El direccionamiento base-indexado.
Modo de direccionamiento registro indirecto.
En el modo de direccionamiento registro indirecto, la direccin
efectiva del dato se calcula tomando como desplazamiento el
contenido de uno de tres registros: BX, SI o DI. El segmento en

los tres casos es el valor del registro de segmento de datos


DS.
El modo de direccionamiento registro indirecto tiene la
siguiente sintaxis:
El direccionamiento registro indirecto se emplea normalmente
para permitir que una instruccin opere en mltiples variables
o elementos de un arreglo. Por ejemplo:
Modo de direccionamiento indexado.
El modo de direccionamiento indexado es similar al modo de
direccionamiento base, slo que utiliza los registros SI o DI en
lugar de los registros BX o BP. Las referencias a SI o DI son
desplazamientos con respecto al registro de segmento de
datos DS.
El modo de direccionamiento base tiene la siguiente sintaxis:

En los dos primeros casos el desplazamiento del dato con


respecto a DS est dado por el valor de SI ms o menos n
bytes. En los dos ltimos casos el desplazamiento del dato
con respecto a DS est dado por el valor de DI ms o menos n
bytes.
El direccionamiento indexado se emplea normalmente para
accesar a los elementos de un arreglo. Por ejemplo, las
siguientes instrucciones almacenan el valor de 6 en el
elemento del arreglo bdtosx cuyo ndice est en la variable
indice:

Por otro lado, las siguientes instrucciones almacenan el valor


de 300 en el elemento del arreglo wdtosx cuyo ndice est en
la variable indice:

Modo de direccionamiento base-indexado.


En el modo de direccionamiento base-indexado, el clculo de
la direccin efectiva del dato emplea dos registros: un registro
base: BX o BP y un registro ndice: SI o DI. Las referencias a
BX son desplazamientos con respecto al registro de segmento
de datos DS mientras que las referencias a BP son
desplazamientos con respecto al registro de segmento de pila
SS.
El modo de direccionamiento base-indexado tiene la siguiente
sintaxis:

En los dos primeros casos el desplazamiento del dato con


respecto a DS est dado por el valor de BX ms SI o DI ms
opcionalmente n bytes. En los dos ltimos casos el
desplazamiento del dato con respecto a SS est dado por el
valor de BP ms SI o DI ms opcionalmente n bytes.
El direccionamiento base-indexado se emplea normalmente
para accesar a los elementos de un arreglo.
Los registros BX o BP pueden contener la direccin base de un
arreglo, los registros SI o DI el desplazamiento del elemento
con respecto a la direccin base del arreglo y luego agregarle
un posible valor n para localizar un campo en este elemento
especfico.

Por ejemplo, las siguientes instrucciones almacenan el valor


de 6 en el elemento del arreglo bdtosx cuyo ndice est en la
variable indice:

Por otro lado, las siguientes instrucciones almacenan el valor


de 300 en el elemento del arreglo wdtosx cuyo ndice est en
la variable indice:
Procedimientos y arreglos.
En muchas ocasiones deseamos que un procedimiento opere
sobre los elementos de un arreglo.
La tcnica ms eficiente es la de pasarle al procedimiento la
direccin del arreglo y as permitirle que accese a los
elementos del arreglo.
Operaciones De Cadenas.
El ensamblador del 8086 posee un conjunto de instrucciones
especiales para procesar arreglos de bytes y de palabras.
Estas instrucciones aunque reciben el nombre de
instrucciones de cadenas operan sobre arreglos de bytes y
palabras sin importar el contenido de los arreglos.
Las instrucciones de cadenas se dividen en tres grupos:
Instrucciones de transferencia de cadenas,
Instrucciones de inspeccin de cadenas y
Prefijos de repeticin de instrucciones.

Todas las instrucciones de cadenas utilizan los registros DS:SI


y ES:DI para realizar su trabajo.

Ambas combinaciones DS:SI y ES:DI se utilizan como ndices


a los arreglos sobre los que se est operando. Al igual que
como lo hemos hecho con el registro de segmento de datos
DS, debemos inicializar el registro de segmento extra ES para
que apunte al segmento que contiene el arreglo al que va
hacerse referencia mediante ES:DI.
Si el programa contiene un slo segmento de datos o si las
cadenas sobre las que se van a operar estn todas en el
mismo segmento de datos la inicializacin puede hacerse de
la siguiente manera:

Si por el contrario, queremos que el registro de segmento


extra ES apunte a otro segmento donde est definida la
variable edato, podemos hacer lo siguiente:

Las instrucciones de cadena adems de realizar su trabajo,


incrementan o decrementan en forma automticamente los
registros ndice que usan.
Las operaciones de byte incrementan o decrementan los
registros SI, DI, o ambos en uno, mientras que las operaciones
de palabras incrementan o decrementan los registros SI, DI, o
ambos en dos.
El que las instrucciones de cadenas incrementen o
decrementen los registros de ndice est controlado por la

bandera de direccin D. Si D = 0, entonces los registros ndice


se incrementan y si D = 1, entonces los registros ndice se
decrementan.
Para establecer el valor de la bandera de direccin se utilizan
las instrucciones: cld y std.
Instruccin CLD.
cld
Coloca un cero en la bandera de direccin.
Sintaxis:
cld
Utilice cld siempre que se va a ejecutar una instruccin de
cadena donde se desee que los registros SI, DI, o ambos se
incrementen automticamente.
La instruccin cld no afecta el resto de las banderas.
Instruccin STD.
std
Coloca un uno en la bandera de direccin.
Sintaxis:
std
Utilice std siempre que se va a ejecutar una instruccin de
cadena donde se desee que los registros SI, DI, o ambos se
decrementen automticamente.
La instruccin cld no afecta el resto de las banderas.
Instrucciones de transferencia de cadenas.
Estas instrucciones permiten mover bytes y palabras de
memoria a un registro, de un registro a memoria o
directamente de memoria a memoria.

lods origen
Carga en el acumulador AX o AL el valor del elemento de un
arreglo cuyo desplazamiento con respecto del principio del
arreglo est dado por SI.
Sintaxis:
El operando de lods es siempre el registro SI que contiene el
desplazamiento del dato con respecto al segmento dado por
DS. Si el arreglo esta en el segmento apuntado por el registro
de segmento extra se puede utilizar el operador: (dos puntos)
que modifica el registro de segmento empleado por omisin.
Para que SI contenga el desplazamiento con respecto al
segmento extra en lugar del segmento de datos escribiremos
es:si en lugar de si.
Cada vez que la instruccin lods se ejecuta, el registro SI se
incrementa o decrementa en uno o dos para que apunte al
siguiente o al anterior elemento del arreglo dependiendo de s
el valor de la bandera de direccin es cero o uno. La
instruccin lods no afecta las banderas.
Instrucciones de transferencia de cadenas.
lodsb | lodsw
lodsb es una abreviatura de lods [byte si] y lodsw es una
abreviatura de lods [word si].
Sintaxis:

movs destino, origen


Copia directamente el valor de un elemento de un arreglo
cuyo desplazamiento con respecto del principio del arreglo
est dado por SI a otro elemento de un segundo arreglo cuyo

desplazamiento con respecto del principio de este segundo


arreglo est dado por DI.
Sintaxis:
El primer operando de movs es siempre el registro DI que
contiene el desplazamiento del destino con respecto al
segmento dado por ES. El segundo operando de movs es
siempre el registro SI que contiene el desplazamiento del
origen con respecto al segmento dado por DS. Si el arreglo
origen esta en el segmento apuntado por el registro de
segmento extra se puede utilizar el operador : (dos puntos)
que modifica el registro de segmento empleado por omisin.
Para que SI contenga el desplazamiento con respecto al
segmento extra en lugar del segmento de datos escribiremos
es:si en lugar de si.
Instrucciones de transferencia de cadenas.
Cada vez que la instruccin movs se ejecuta, ambos los
registros SI y DI se incrementan o decrementan en uno o dos
dependiendo del nmero de bytes copiados. Si la bandera de
direccin vale 0, los registros se incrementan y si la bandera
de direccin vale 1 los registros se decrementan.
La instruccin movs no afecta las banderas.
Instrucciones de transferencia de cadenas.
stos destino
Carga el valor en el acumulador AX o AL al elemento de un
arreglo cuyo desplazamiento con respecto del principio del
arreglo est dado por DI.
Sintaxis:

El operando de stos es siempre el registro DI que contiene el


desplazamiento del destino con respecto al segmento dado
por ES.
Cada vez que la instruccin stos se ejecuta, el registro DI se
incrementa o decrementa en uno o dos para que apunte al
siguiente o al anterior elemento del arreglo dependiendo de si
el valor de la bandera de direccin es cero o uno.
La instruccin stos no afecta las banderas.
Instrucciones de inspeccin de cadenas.
Estas instrucciones permiten comparar y revisar bytes y
palabras buscando valores especficos.
cmps origen, destino
Compara el valor del elemento de un arreglo cuyo
desplazamiento con respecto del principio del arreglo est
dado por SI con el valor del elemento de un segundo arreglo
cuyo desplazamiento con respecto del principio de este
segundo arreglo est dado por DI.
Sintaxis:
El primer operando de cmps es siempre el registro SI que
contiene el desplazamiento de origen con respecto al
segmento dado por DS. El segundo operando de cmps es
siempre el registro DI que contiene el desplazamiento de
destino con respecto al segmento dado por DS. Si el arreglo
origen est en el segmento apuntado por el registro de
segmento extra se puede utilizar el operador : (dos puntos)
que modifica el registro de segmento empleado por omisin.
Para que SI contenga el desplazamiento con respecto al
segmento extra en lugar del segmento de datos escribiremos
es:si en lugar de si.
Instrucciones de inspeccin de cadenas.

La instruccin cmps efecta la resta [origen] - [destino], tira el


resultado y almacena las bandera en la misma forma en que
trabaja la instruccin cmp.
Cada vez que la instruccin cmps se ejecuta, ambos los
registros SI y DI se incrementan o decrementan en uno o dos
dependiendo del nmero de bytes copiados. Si la bandera de
direccin vale 0, los registros se incrementan y si la bandera
de direccin vale 1 los registros se decrementan.
La instruccin cmps afecta las banderas de sobreflujo O, signo
S, cero Z, acarreo auxiliar A, paridad Py acarreo C.
Prefijos de repeticin de instrucciones.
Los prefijos de repeticin de instrucciones son mnemnicos
que preceden a las instrucciones de cadenas para crear
comandos que se repitan un nmero de veces o hasta que se
cumpla una condicin.
rep
Este prefijo repite la instruccin de cadena que le sigue un
nmero de veces especificado por el registro CX.
Sintaxis:

También podría gustarte