Está en la página 1de 24

TECNOLOGICO NACIONAL DE MEXICO.

INGENIERIA EN SISTEMAS COMPUTACIONALES.


LENGUAJE DE INTERFAZ.

UNIDAD III. MODULARIZACION.


3.1 Introducción.
La programación modular, es uno de los métodos de diseño más flexibles y poderosos, para el
mejoramiento de la productividad de un programa. Usando la programación modular, el problema se divide en
partes, donde cada una ejecuta una única actividad o tarea. Cada uno de estos módulos se analiza, se codifica
y se prueba de preferencia por separado.

Al trabajar con lenguaje ensamblador, la necesidad de la estructuración es, si existe la posibilidad, aún
más trascendente, puesto que cualquier tarea, por sencilla que parezca, puede requerir una gran lista de
sentencias ejecutables. No hay que olvidar que estamos trabajando a un nivel muy bajo, más que cualquier
otro lenguaje al que esté acostumbrado.

Todo programa contiene un módulo denominado programa principal que controla todo lo que sucede; si
se transfiere el control a un sub-módulo, éste ejecuta su función y una vez que la termina, regresa el control al
módulo desde donde fue llamado y en muchos casos es el módulo principal.

Principal

Limpiar Capturar Procesar Mensajes Resultado


Pantalla Datos de salida

Si la tarea asignada a cada sub-módulo es demasiado compleja, éste deberá descomponerse en otros
módulos más pequeños. Este proceso de descomposición continúa hasta que cada módulo tenga una tarea
específica que ejecutar.

Esta tarea puede ser:


a) Entrada.
b) Salida.
c) Manipulación de datos.
d) Control de otros módulos.
e) Alguna combinación de los anteriores.

En el lenguaje ENSAMBLADOR esta técnica se puede llevar a cabo mediante Macros y


Procedimientos.

Agosto – Diciembre 2018 Pág. – 111 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

3.2 Procedimientos.

Los lenguajes de alto nivel, al menos la mayoría de ellos, permite codificar bloques de sentencias a los
que se asigna un nombre, de tal forma que para ejecutar dichas sentencias, desde cualquier punto de la
aplicación basta con introducir ese identificador y, en caso necesario, facilita los parámetros adecuados. A
estos bloques de sentencias, dependiendo del lenguaje, se les conoce como procedimientos, funciones o
métodos, según los casos.

En ensamblador se opera con direcciones, a pesar de que éstas pueden estar representadas mediante
etiquetas que hacen más fácil nuestro trabajo. La transferencia mágica de parámetros, por la que unos valores
facilitados tras un identificador aparecen como argumentos del procedimiento invocado, es algo que no existe.
Sí tenemos a nuestra disposición, no obstante, una instrucción capaz de saltar a una dirección dada guardando
el actual valor del registro IP, de tal forma que ésta puede recuperarse posteriormente para volver y continuar la
ejecución por el punto en el que se interrumpió.

La instrucción que nos permite invocar a un procedimiento es CALL. Esta toma como parámetro un
valor inmediato, la dirección a la que debe transferir el control, o bien indirecto a través de un registro o un
campo que contendrá la dirección a la que tiene que apuntar IP a partir de ese momento.

Aparentemente CALL es similar a la instrucción JMP, ya que transfiere la ejecución a una dirección de
forma incondicional. La diferencia es que, antes de que se produzca ese salto, CALL guarda en la pila el valor
actual del registro IP, en caso de que el salto sea una dirección dentro del mismo segmento que indica CS, o
bien, los valores de CS e IP, si el salto es a una dirección de otro segmento. El primer tipo de salto se
denomina NEAR o cercano, mientras que el segundo se le conoce como salto FAR o lejano. En el primero se
necesitan 16 bits, tan sólo la dirección relativa al segmento que indica CS y en el segundo los 32 bits precisos
para dar valor a CS e IP tras guardarlos en la pila.

Una vez que se ha guardado el valor de IP o de CS e IP, se ejecutan las instrucciones que haya en la
dirección indicada. Estas pueden efectuar, como es lógico, cualquier tarea, siempre que tengamos en cuenta
que al llegar al final, justo antes de devolver el control, la pila debe encontrarse en la misma situación en la que
se encontraba al principio. Si hemos introducido valores, éstos deben extraerse. Lo importante es que el
puntero de la pila, en el momento de volver, esté apuntando a los valores que introdujo en ella la instrucción
CALL. Si la instrucción CALL guarda el actual puntero de instrucción y transfiere la ejecución al procedimiento,
la instrucción RET tiene el efecto inverso, recuperándose la dirección de la pila, devolviéndola a CS e IP e
incrementando éste último para proceder a ejecutar la instrucción que sigue al CALL que invocó el
procedimiento.

La instrucción RET, por tanto, también es un salto incondicional, similar a JMP, con la diferencia de que
la dirección a la que saltará debe estar almacenada en la pila, generalmente por una llamada previa a CALL.
Teniendo en cuenta esto, entenderá lo importante que es que SS:SP conserven los valores que tenían al iniciar
la ejecución del procedimiento, porque, de no ser así, la instrucción RET podría transferir la ejecución a un
punto incorrecto y causar la caída del sistema.

¿Cómo sabrá la instrucción RET si debe recuperar de la pila sólo el valor de IP o también el de CS? La
respuesta es que depende de cómo se haya definido el procedimiento al que se invocó con CALL. MASM y
TASM cuentan con un preprocesador que, a partir de ciertas palabras claves como PROC FAR o PROC NEAR,
se encargan de generar las instrucciones ensamblador adecuadas.

Agosto – Diciembre 2018 Pág. – 112 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

Sintaxis:
etiqueta PROC [NEAR | FAR]
secuencia de sentencias
RET constante
etiqueta ENDP

Donde:
etiqueta: Es un símbolo asignado como nombre al procedimiento, la distancia pude ser NEAR ó FAR,
cualquier RET dentro del PROCEDIMIENTO automáticamente toma la misma distancia.

constante: STACK se usa para pasar argumentos a un procedimiento, si se conoce el número de WORDS
pasadas al STACK como argumentos, constante puede contener ese número, de tal forma de
liberar esos argumentos después de salir del procedimiento.

La etiqueta se usa para llamar al PROCEDIMIENTO con una instrucción CALL, entonces, la etiqueta
contiene la dirección de inicio de la primera instrucción del procedimiento. Esta instrucción realiza su trabajo
colocando en el STACK la dirección de la siguiente instrucción y transfiriendo el control a la dirección
especificada por el operando. para una llamada NEAR, SP es decrementado en dos y el offset es cargado en el
STACK ; el nuevo offset es cargado en IP.

Sintaxis:
CALL etiqueta

etiqueta: Es el nombre del procedimiento; se transforma en la dirección del procedimiento.

Veamos un ejemplo:
TITLE ENSA34.ASM
COMMENT *Divide el contenido de una variable entre 8 como división entera, el resultado lo pone en otra
variable.*
.MODEL SMALL ;Define el modelo de memoria a usar
.STACK 20h ;Define el tamaño del STACK

.CONST
oper DB 10, 13, 'Operación: b = a DIV 8 $'
leta DB 10, 13, 'El valor de a es : $'
letb DB 10, 13, 'El valor de b es : $'

.DATA
a DW 45600 ;Define a como WORD y se inicializa.
b DW ? ;Define como WORD a b y no se inicializa.
ascval DB 6 Dup('$') ;Area para almacenar la cadena que representa el número, del tipo WORD

.CODE ;Inicia el segmento de código.


inicio:
mov ax, DGROUP ;Pone el inicio del segmento de datos en el registro DS
mov ds, ax
mov dx, offset oper ;Manda a pantalla la cadena oper
mov ah, 09h
int 21h

Agosto – Diciembre 2018 Pág. – 113 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

mov dx, offset leta ;Manda imprimir letrero para a.


mov ah, 09h
int 21h
lea bx, a ;Copia la dirección de a en BX.
call uno
mov bx, a ;Copia el contenido de a en BX OPERACION b = a DIV 8
mov cl, 3 ;Realiza la operación de DIV
shr bx, cl ;mediante un corrimiento a la derecha de 3
mov b, bx ;Copia el contenido de BX en b
mov dx, offset letb ;Manda imprimir letrero para b.
mov ah, 09h
int 21h
lea bx, b ;Copia la dirección de b en BX
call uno
mov ax, 4C00h ;Inicia la rutina de salida.
int 21h

uno PROC NEAR


lea si, ascval
mov cx, 6
ciclo:
mov BYTE PTR [si], 24h
inc si ;Limpia con '$' la cadena ascval
loop ciclo
mov cx, 0010 ;Pone en CX el factor de División
lea si, ascval + 4 ;Pone en SI la última dirección
mov ax, [bx] ;Pone en AX el contenido de bx
c20:
cmp ax, 0010 ;Valor < que 10
jb c30 ;Si lo es, SALE
xor dx, dx ;Limpia DX
div cx ;Divide por 10
or dl, 30h ;Ve a que valor corresponde
mov [si], dl ;Almacena carácter ASCII
dec si
jmp c20
c30:
or al, 30h ;Almacena último resultado
mov [si], al ;como carácter ASCII
mov dx,si
mov ah, 09h
int 21h
ret
uno ENDP
END inicio

OBSERVACIONES.
Este programa almacena un número en la variable a, con este valor realiza una división entera entre 8.
Usamos un procedimiento UNO para presentar primero el valor de a y luego el valor del resultado en b.

Agosto – Diciembre 2018 Pág. – 114 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

El mapa de memoria nos resulta:

Start Stop Length Name Class


00000H 0006AH 0006BH _TEXT CODE
0006CH 00075H 0000AH _DATA DATA
00076H 000BBH 00046H CONST DATA
000C0H 000DFH 00020H STACK STACK

Program entry point at 0000:0000

Nota: se usó el Turboassembler para el ensamblado.

Veamos el desensamble.

-u 0 L 67
15B4:0000 B8BB15 MOV AX,15BB
15B4:0003 8ED8 MOV DS,AX
15B4:0005 BA0A00 MOV DX,000A
15B4:0008 B409 MOV AH,09
15B4:000A CD21 INT 21
15B4:000C BA2400 MOV DX,0024
15B4:000F B409 MOV AH,09
15B4:0011 CD21 INT 21
15B4:0013 BB0000 MOV BX,0000
15B4:0016 E81E00 CALL 0037
15B4:0019 8B1E0000 MOV BX,[0000]
15B4:001D B103 MOV CL,03
15B4:001F D3EB SHR BX,CL
15B4:0021 891E0200 MOV [0002],BX
15B4:0025 BA3A00 MOV DX,003A
15B4:0028 B409 MOV AH,09
15B4:002A CD21 INT 21
15B4:002C BB0200 MOV BX,0002
15B4:002F E80500 CALL 0037
15B4:0032 B8004C MOV AX,4C00
15B4:0035 CD21 INT 21
15B4:0037 BE0400 MOV SI,0004
15B4:003A B90600 MOV CX,0006
15B4:003D C60424 MOV BYTE PTR [SI],24
15B4:0040 46 INC SI
15B4:0041 E2FA LOOP 003D
15B4:0043 B90A00 MOV CX,000A
15B4:0046 BE0800 MOV SI,0008
15B4:0049 8B07 MOV AX,[BX]
15B4:004B 3D0A00 CMP AX,000A
15B4:004E 720C JB 005C
15B4:0050 33D2 XOR DX,DX
15B4:0052 F7F1 DIV CX
15B4:0054 80CA30 OR DL,30
15B4:0057 8814 MOV [SI],DL

Agosto – Diciembre 2018 Pág. – 115 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

15B4:0059 4E DEC SI
15B4:005A EBEF JMP 004B
15B4:005C 0C30 OR AL,30
15B4:005E 8804 MOV [SI],AL
15B4:0060 8D14 LEA DX,[SI]
15B4:0062 B409 MOV AH,09
15B4:0064 CD21 INT 21
15B4:0066 C3 RET
-q
Note que la etiqueta de CALL es substituida por el OFFSET 0037h, que es la dirección de inicio del
PROCEDIMIENTO. Nota que ya no existe ningún MACRO éstos fueron substituidos en tiempo de ENSAMBLE.

Por último vamos a analizar el PROCEDIMIENTO (UNO) él cuál pasa el WORD a cadena para poderla
imprimir en pantalla.

Algoritmo usado en el procedimiento UNO.

Para imprimir o mostrar un resultado aritmético es necesario convertirlo a formato ASCII. El proceso
consiste en dividir el número binario entre 10 (0Ah) sucesivamente hasta que el resultado sea menor que 10
(0Ah). El residuo el cual esta solo entre 0 - 9, genera el carácter ASCII.

Como ejemplo convirtamos el número 1234 (4D2h) en su representación decimal como ASCII.
Cociente Residuo ASCII

4D2/A = 7B 4 30+4 34
7B/A = C 3 30+3 33
C/A = 1 2 30+2 32
1 30+1 31

La lectura correcta será de abajo hacia arriba, el primer número que se obtiene es el menos significativo
y el último (resultado de la división) es el más significativo. El proceso podemos resumirlo en los siguientes
pasos

1. Colocar en: CX = 0Ah


2. Poner en SI la penúltima dirección de la cadena.
La última la dejamos para el signo ($).
3. Ponemos el número a convertir en AX.
4. Comparamos si el número es menor que 10 (0Ah). Si lo es solo queda convertir este resultado a ASCII
(9)
5. Efectuamos la división entre 10 (0Ah) si usamos la instrucción DIV el resultado queda de la siguiente
forma:
* Resultado en AX. Nos sirve para efectuar otra división:
* Residuo en DX (limpiamos antes DX)
6. Convertimos el residuo a ASCII
7. El valor ASCII lo ponemos en la dirección donde apunta SI
8. Decrementar SI
9. Regresamos al punto 4.
10. Convertimos el último resultado a ASCII.
11. Mandamos a pantalla la cadena.

Agosto – Diciembre 2018 Pág. – 116 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

3.3 Macros.

Para cada instrucción simbólica que el programador codifica, en ensamblador, genera una instrucción
en lenguaje máquina. Pero para cada enunciado codificado en un lenguaje de alto nivel, como C o Pascal, el
compilador genera muchas instrucciones de lenguaje máquina. A este respecto, se puede pensar, en un
lenguaje de alto nivel consistente de macro enunciados.

El ensamblador tiene facilidades que el programador puede usar para definir macros. Es necesario
definir un nombre específico para la macro, junto con el conjunto de instrucciones en ensamblador que la macro
va a generar. Después, siempre que necesite codificar el conjunto de instrucciones, sólo codifique el nombre de
la macro y el ensamblador genera de manera automática las instrucciones que el programador definió.

Las macros son útiles para los siguientes propósitos:


 Simplificar y reducir la cantidad de codificación repetitiva.
 Reducir errores causados por la codificación repetitiva.
 Linealizar un programa en ensamblador, para hacerlo más legible.

Para macros que se necesiten incluir en un programa, primero tiene que definirlas. Una definición de
macro aparece antes de cualquier definición de segmento. La sintaxis de la macro es la siguiente:

nombre MACRO [parámetro [,parámetro]....]


secuencia de sentencias.
ENDM
Donde:
nombre: Deberá ser único, y reunir los requisitos de un símbolo, con él podemos invocar al macro.
parámetros: Son símbolos que actúan como receptores de valores pasados como argumento a la MACRO
cuando ésta es llamada. El número máximo de parámetros deberán caber en una línea.

Examinaremos una definición de macro sencilla que inicializa los registros de segmento para un
programa .EXE
INICIALIZA MACRO
MOV AX, @DATA
MOV DS, AX
MOV ES, AX
ENDM

El nombre de esta macro es INICIALIZA, aunque es aceptable cualquier otro nombre válido que sea
único. La directiva MACRO en la primer línea le indica al ensamblador que las instrucciones que siguen hasta
ENDM (“fin de la macro”), son parte de la definición de la macro. Las instrucciones entre MACRO y ENDM
comprenden el cuerpo de la definición de la macro.

Los nombres a los que se hace referencia en la definición de la macro, @DATA, AX,DS y ES, deben de
estar definidos en alguna parte del programa o deben de ser dados a conocer de alguna otra forma al
ensamblador. En forma subsecuente se puede utilizar la macroinstrucción INICIALIZA en el segmento de
código en donde se quiera inicializar los registros. Cuando el ensamablador encuentra la macroinstruccion,
busca en una tabla de instucciones simbólicas y, a falta de una entrada, busca macroinstucciones. Ya que el
programa contiene una definición de la macro INICIALIZA, el ensamblador sustituye el cuerpo de la definición,
generando las instrucciones: expansión de la macro. Un programa utilizaría la macroinstrucción INICIALIZA
una sola vez, aunque otras macros estan diseñadas para ser utilizadas cualquier número de veces y cada vez
que el ensamblador genere la misma expansión de la macro.

Agosto – Diciembre 2018 Pág. – 117 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

Para hacer la macro más flexible, se pueden definir parámetros en ella como argumentos mudos. La
definición de la macro siguiente llamada PROMPT, proporciona el uso de la función 09h del DOS para
desplegar cualquier mensaje.

PROMPT MACRO MENSAJE


MOV AH, 09H
LEA DX, MENSAJE
INT 21H
ENDM
Cuando se usa la macroinstrucción, el programador debe proporcionar el nombre del mensaje, el cual
hace referencia en el segmento de datos terminada por un signo de pesos ($). Un argumento mudo, en una
definición de una macro, indica al ensamblador que haga coincidir su parámetro con cualquier aparición del
mismo parámetro en el cuerpo de la macro. Por ejemplo, el argumento mudo MENSAJE también aparece en la
instrucción LEA.

Veamos algunos ejemplos: Primero retomaremos el ensa34.asm para transformarlo usando macros

TITLE ENSA34A.ASM
COMMENT * Divide el contenido de una variable entre 8 como división entera, el resultado lo pone en otra
variable.*

imp_cad MACRO d ;Macro para mandar una cadena terminada en ‘$’ a pantalla.
lea dx, d
mov ah, 09h
int 21h
ENDM

.MODEL SMALL ;Define el modelo de memoria a usar

.STACK 20h ;Define el tamaño del STACK

.CONST
oper DB 10, 13, 'Operación: b = a DIV 8 $'
leta DB 10, 13, 'El valor de a es : $'
letb DB 10, 13, 'El valor de b es : $'

.DATA
a DW 45600 ;Define a como WORD y se inicializa.
b DW ? ;Define como WORD a b y no se inicializa.
ascval DB 6 Dup('$') ;Area para almacenar la cadena que representa el número, del tipo WORD

.CODE ;Inicia el segmento de código.


inicio:
mov ax, DGROUP ;Pone el inicio del segmento de datos en el registro DS
mov ds, ax
imp_cad oper ;Manda a pantalla la cadena oper
imp_cad leta ;Manda imprimir letrero para a.

lea bx, a ;Copia la dirección de a en BX.


call uno ; Invoca al procedimiento UNO

Agosto – Diciembre 2018 Pág. – 118 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

mov bx, a ;Copia el contenido de a en BX OPERACION b = a DIV 8


mov cl, 3 ;Realiza la operación de DIV
shr bx, cl ;mediante un corrimiento a la derecha de 3
mov b, bx ;Copia el contenido de BX en b
imp_cad letb ;Manda imprimir letrero para b.
lea bx, b ;Copia la dirección de b en BX
call uno
mov ax, 4C00h ;Inicia la rutina de salida.
int 21h

uno PROC NEAR


lea si, ascval
mov cx, 6

ciclo:
mov BYTE PTR [si], 24h
inc si ;Limpia con '$' la cadena ascval
loop ciclo
mov cx, 0010 ;Pone en CX el factor de División
lea si, ascval + 4 ;Pone en SI la última dirección
mov ax, [bx] ;Pone en AX el contenido de bx
c20:
cmp ax, 0010 ;Valor < que 10
jb c30 ;Si lo es, SALE
xor dx, dx ;Limpia DX
div cx ;Divide por 10
or dl, 30h ;Ve a que valor corresponde
mov [si], dl ;Almacena carácter ASCII
dec si
jmp c20
c30:
or al, 30h ;Almacena último resultado
mov [si], al ;como carácter ASCII
imp_cad [si]
ret
uno ENDP

END inicio

OBSERVACIONES.
Este programa almacena un número en la variable a, con este valor realiza una división entera entre 8.
usamos un procedimiento UNO para presentar primero el valor de a y luego el valor del resultado en b.

Para la presentación en la pantalla usamos una MACRO llamada imp_cad, a la cual le pasamos como
argumento la variable inicial de la cadena. Si observamos el código desensamblado vemos que en el archivo
.EXE el nombre de la MACRO fue substituido por su código en cada parte donde fue llamada, sin embargo para
el procedimiento no sucedió tal cosa, la etiqueta de la llamada fue substituida por la dirección de inicio del
código del procedimiento.

Agosto – Diciembre 2018 Pág. – 119 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

; ENSA 35.ASM. Uso de una macro simple

imp_cad MACRO d ;Imprime una cadena terminada en ‘$’


lea dx, d ;Recibe como argumento la variable o nombre de la cadena
mov ah, 09h
int 21h
ENDM

.MODEL Small
.STACK 100h

.DATA
x DB "Instituto Tecnológico de la Laguna"
DB 13, 10, 24h
y DB "Blvd. Revolución y Calzada Cuauhtémoc"
DB 13, 10, 24h
z DB "Torreón, Coah."
DB 13, 10, 24h

.CODE
inicio:
mov ax, @data
mov ds, ax
imp_cad x ;Imprime la cadena x
imp_cad y ;Imprime la cadena y
imp_cad z ;Imprime la cadena z
mov ax, 4C00h
int 21h
END inicio

OBSERVACIONES.
Note que la definición de la macro se hizo fuera de cualquier segmento. Si observamos el desensamble
del programa anterior vemos que la macro es escrita tres veces, que es el número de veces que es llamada.

-u 0 L 1E
15B4:0000 B8B615 MOV AX,15B6
15B4:0003 8ED8 MOV DS,AX
15B4:0005 BA0000 MOV DX,0000
15B4:0008 B409 MOV AH,09
15B4:000A CD21 INT 21
15B4:000C BA250 MOV DX,0025
15B4:000F B409 MOV AH,09
15B4:0011 CD21 INT 21
15B4:0013 BA4D00 MOV DX,004D
15B4:0016 B409 MOV AH,09
15B4:0018 CD21 INT 21
15B4:001A B8004C MOV AX,4C00
15B4:001D CD21 INT 21
-q

Agosto – Diciembre 2018 Pág. – 120 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

Algunas macros necesitan que se definan elementos de datos y etiquetas de instrucciones dentro de la
definición de la macro. Si utiliza la macro más de una vez en el mismo programa y el ensamblador define los
elementos de datos para cada aparición, los nombres duplicados harían que el ensamblador generará un
mensaje de error. Para asegurar que cada nombre generado sea único, codifique la directiva LOCAL
inmediatamente después de la instrucción macro. La directiva EXITM nos permite abandonar una macro antes
de haberse concluido la lectura de todas las sentencias.

En el siguiente ejemplo se trata de mostrar el uso de las directiva LOCAL y EXITM, aunque esta última
no tenga mucho sentido, ya que fue escrita al final de la macro

;ENSA36.ASM, Uso de macros

prints MACRO cad, len ;Esta MACRO imprime una cadena tomando en cuenta su longitud.
LOCAL uno, dos ;Para ello recibe 2 argumentos, el nombre
mov si, offset cad ;de la cadena y su longitud.
mov cx, len ;La impresión la realiza utilizando la función 02h de la INT 21h.
mov ah, 02h
uno:
mov dl, BYTE PTR [si] ;SI contiene la dirección de del carácter que se va a imprimir.
int 21h
inc si
dec cx ;CX lleva la cuenta de los caracteres impresos.
jcxz dos
jmp short uno
dos:
EXITM ;indica que cuando CX  0 se sale de la macro.
ENDM

.MODEL SMALL
.STACK 100h
.DATA
a DB "Siempre que haya un hueco en tu vida", 10, 13
b DW $ - a
c DB "Llenalo de amor", 10, 13
d DW $ - c
e DB "Adolescente, joven, viejo", 10, 13
f DW $ - e
;las variables b, d, f. Contienen la longitud de cada cadena.
.CODE
inicio:
mov ax, @data
mov ds, ax
prints a, b ;Imprime la cadena a
prints c, d ;Imprime la cadena c
prints e, f ;Imprime la cadena e
prints a, b ;Imprime la cadena a
prints c, d ;Imprime la cadena c
mov ax, 4C00h
int 21h
END inicio

Agosto – Diciembre 2018 Pág. – 121 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

OBSERVACIONES.
Esta rutina de impresión no es una buena candidata para ser una MACRO, ya que estas deberán de ser
cortas, de tal manera de al ser incluidas en el código no lo hagan crecer mucho, como podemos ver si
observamos el desensamble.

-U 0 L 68
15B4:0000 B8BB15 MOV AX,15BB
15B4:0003 8ED8 MOV DS,AX
15B4:0005 BE0000 MOV SI,0000
15B4:0008 8B0E2600 MOV CX,[0026
15B4:000C B402 MOV AH,02
15B4:000E 8A14 MOV DL,[SI]
15B4:0010 CD21 INT 21
15B4:0012 46 INC SI
15B4:0013 49 DEC CX
15B4:0014 E302 JCXZ 0018
15B4:0016 EBF6 JMP 000E
15B4:0018 BE2800 MOV SI,0028
15B4:001B 8B0E3900 MOV CX,[0039]
15B4:001F B402 MOV AH,02
15B4:0021 8A14 MOV DL,[SI]
15B4:0023 CD21 INT 21
15B4:0025 46 INC SI
15B4:0026 49 DEC CX
15B4:0027 E302 JCXZ 002B
15B4:0029 EBF6 JMP 0021
15B4:002B BE3B00 MOV SI,003B
15B4:002E 8B0E5500 MOV CX,[0055]
15B4:0032 B402 MOV AH,02
15B4:0034 8A14 MOV DL,[SI]
15B4:0036 CD21 INT 21
15B4:0038 46 INC SI
15B4:0039 49 DEC CX
15B4:003A E302 JCXZ 003E
15B4:;003CEBF6 JMP 0034
15B4:003E BE0000 MOV SI,0000
15B4:0041 8B0E2600 MOV CX,[0026]
15B4:0045 B402 MOV AH,02
15B4:0047 8A14 MOV DL,[SI]
15B4:0049 CD21 INT 21
15B4:004B 46 INC SI
15B4:004C 49 DEC CX
15B4:004D E302 JCXZ 0051
15B4:004F EBF6 JMP 0047
15B4:0051 BE2800 MOV SI,0028
15B4:0054 8B0E3900 MOV CX,[0039]
15B4:0058 B402 MOV AH,02
15B4:005A 8A14 MOV DL,[SI]
15B4:005C CD21 INT 21
15B4:005E 46 INC SI

Agosto – Diciembre 2018 Pág. – 122 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

15B4:005F 49 DEC CX
15B4:0060 E302 JCXZ 0064
15B4:0062 EBF6 JMP 005A
15B4:0064 B8004C MOV AX,4C00
15B4:0067 CD21 INT 21

-q

Comparativa entre macros y procedimientos.

Ventajas de las MACROS.


1. Son rápidas porque se ejecutan en línea en un programa.
2. Las macros pueden pasar y recibir parámetros.
3. La estructura de una MACRO es simple.
4. Hacen más legible un programa.

Desventajas de las MACRO


1. Hacen grande el código fuente.

Ventajas de los PROCEDIMIENTOS.


1. Reducen el código
2. Hacen más legible un programa.

Desventajas de los PROCEDIMIENTOS.


1. Hacen más lenta la ejecución de un programa.
2. Es un poco más compleja su declaración.
3. Un procedimiento no puede recibir parámetros.

Sugerencias para el uso de macros y procedimientos.

Seleccione una MACRO para:


 Rutinas cortas.
 Rutinas que no son llamadas frecuentemente.
 Si esta creando o experimentando con un programa.

Seleccione un PROCEDIMIENTO para:


 Si la rutina es larga.
 Si la rutina es llamada muchas veces.

Nota: Cuando una rutina es llamada frecuentemente y se convierte en una herramienta para nuestros
programas, es conveniente colocarla en una BIBLIOTECA.

Agosto – Diciembre 2018 Pág. – 123 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

3.4. Directivas para programas que usan varios módulos.

Sobre todo cuando un programa es grande, es conveniente dividirlo en módulos y ensamblar solo
aquellos en los que tenemos todavía problemas, los módulos que ya están trabajando, los dejamos como
archivos objeto (.OBJ) y solo los enlazamos con aquellos que ya hemos corregido y ensamblado. Este proceso
ahorra tiempo y posibles errores al modificar involuntariamente módulos que ya están trabajando.

Al ensamblar y enlazar varios módulos para formar un solo archivo .EXE debemos tomar en cuenta
algunas consideraciones básicas. Los símbolos declarados dentro de un módulo son privados del módulo y no
son conocidos en otra parte del programa a menos que así lo indiquemos usando la directiva PUBLIC.

3.4.1. La directiva PUBLIC

Se usa para declarar símbolos públicos de tal manera de permitir que ellos puedan ser accesados
desde otros módulos. Si un símbolo no es declarado como público el nombre del símbolo no se escribe al
archivo objeto. El símbolo tiene el valor de su dirección de OFFSET durante el ensamblado, pero el nombre y
dirección no están disponibles para el enlazador.
Si el símbolo se declara público, su nombre es asociado con su dirección de OFFSET en el archivo
.OBJ. Durante el enlazado, los símbolos en diferentes módulos pero con el mismo nombre son referenciados a
la misma dirección.

Sintaxis:
PUBLIC nombre [, nombre]

Donde
nombre: Es el nombre de una variable, etiqueta o constante numérica definida dentro del archivo presente.

La declaración PUBLIC puede ponerse en cualquier parte del archivo fuente. Los símbolos declarados
PUBLIC dentro de un módulo van a ser usados en otro archivo en el cual no se han declarado (ni pueden ser
declarados), sin embargo el ensamblador marca un error al no encontrar su declaración. Para indicarle al
ensamblador que están declarados en otro módulo, usamos la directiva EXTRN.

Si el enlazador no encontró la declaración de los símbolos manejados como EXTRN, se enviará el


siguiente mensaje:
UNRESOLVED EXTERNALS nombre del símbolo.

Por lo anterior se concluye que, si un símbolo referenciado como PUBLIC en el módulo donde es
declarado, en el módulo donde es usado deberá ser referenciado como EXTRN.

3.4.2 La directiva EXTRN

Se emplea cuando un símbolo es usado en un módulo y no es declarado en él.


Sintaxis:
EXTRN nombre:tipo [, nombre:tipo]...

Agosto – Diciembre 2018 Pág. – 124 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

El tipo deberá ser el mismo dado al símbolo en el módulo donde es declarado. El tipo puede ser uno de
los siguientes:

Descripción Tipos

Especificador de distancia NEAR, FAR, ó PROC


Especificador de tamaño BYTE, WORD, DWORD, FWORD, QWORD ó
TBYTE
Absoluto ABS

El tipo ABS se usa para símbolos que representan números constantes declaradas con EQU.

El tipo PROC representa el tipo por default para un procedimiento, el tipo por default es definido al declarar el
modelo de memoria utilizado.

* NEAR Es una etiqueta (semejante como procedimiento) deberá declararse en el segmento de código desde el
cual los símbolos son utilizados.

* FAR Es una etiqueta la cual puede ser declarada en cualquier parte del archivo fuente, es conveniente hacer
la declaración en el segmento de código donde los símbolos son utilizados.

* Para declarar datos usando EXTRN, la declaración deberá hacerse en el segmento donde ellos son
definidos. Si en el módulo no existe un segmento de datos, deberá declararse uno para usar EXTRN y
referenciar una variable no declarada.

* Los símbolos absolutos pueden ser declarados en cualquier parte del archivo fuente.

Retomando el programa ENSA34, se va a dividir en dos módulos, uno se va a llamar ENSA34B y el


otro, el cual contiene el procedimiento UNO, se llamará BINASIP. Para seguir usando el macro imp_cad, como
éste es agregado al programa en tiempo de ensamble, se deberá usar la directiva INCLUDE.

La directiva INCLUDE inserta código fuente desde un archivo específico al archivo fuente en donde la
directiva es dada.
Sintaxis:
INCLUDE nom_arch

Donde:
nom_arch: Especifica un archivo existente el cual contiene sentencias válidas. Si el archivo se encuentra
en el directorio actual se puede dar solo el nombre del archivo, si no, debe darse tanto la
trayectoria como el nombre del archivo.

Los archivos INCLUDE normalmente contienen; macros, constantes y definiciones, los


PROCEDIMIENTOS se escriben en módulos .OBJ separados, o en bibliotecas.

 Archivo ENSA34B

COMMENT *ENSA34B.ASM. Realiza la operación A = B DIV 8 *

INCLUDE IMP.MAC

.MODEL SMALL ;Define el modelo de memoria a usar

Agosto – Diciembre 2018 Pág. – 125 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

.STACK 20h ;Define el tamaño del STACK


.CONST
oper DB 10, 13, 'Operación: b = a DIV 8 $'
leta DB 10, 13, 'El valor de a es : $'
letb DB 10, 13, 'El valor de b es : $'

.DATA
a DW 45600 ;Define a como WORD y se inicializa.
b DW ? ;Define como WORD a b y no se inicializa.

.CODE ;Inicia el segmento de código.


EXTRN UNO:NEAR
Inicio:
mov ax,DGROUP ;Pone el inicio del segmento de datos
mov ds, ax ;en el registro DS
imp_cad oper ;Manda a pantalla la cadena oper
imp_cad leta ;Manda imprimir letrero para a.
lea bx, a ;Copia la dirección de a en BX.
call uno
mov bx, a ;Copia el contenido de a en BX
;OPERACION b = a DIV 8
mov cl, 3 ;Realiza la operación de DIV
shr bx, cl ;mediante un corrimiento a la derecha de 3
mov b, bx ;Copia el contenido de BX en b
imp_cad letb ;Manda imprimir letrero para b.
lea bx, b ;Copia la dirección de b en BX
call uno
mov ax, 4C00h ;Inicia la rutina de salida.
int 21h
END inicio

 Archivo IMP.MAC

imp_cad MACRO d
lea dx, d
mov ah, 9h
int 21h
ENDM

 Archivo BINASIP.ASM

;BINASIP.ASM. Procedimiento para convertir un número de tipo Word a cadena.


;La dirección de inicio de la cadena deberá estar en DS:DX

PUBLIC UNO

INCLUDE IMP.MAC

.MODEL Small

Agosto – Diciembre 2018 Pág. – 126 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

.STACK 20h.
.DATA
ascval DB 6 Dup('$').CODE
uno PROC NEAR
lea si, ascval
mov cx, 6
ciclo:
mov BYTE PTR [si], 24h
inc si ;Limpia con '$' la cadena ascval
loop ciclo
mov cx, 0010 ;Pone en CX el factor de División
lea si, ascval + 4 ;Pone en SI la última dirección
mov ax, [bx] ;Pone en AX el contenido de bx
c20:
cmp ax, 0010 ;Valor < que 10
jb c30 ;Si lo es, SALE
xor dx, dx ;Limpia DX
div cx ;Divide por 10
or dl, 30h ;Ve a que valor corresponde
mov [si], dl ;Almacena caracter ASCII
dec si
jmp c20
c30:
or al, 30h ;Almacena último resultado
mov [si], al ;como carácter ASCII
imp_cad [si]
ret
uno ENDP
END

OBSERVACIONES.
En este ejemplo el símbolo compartido por ambos archivos es el nombre del procedimiento UNO, en el
archivo donde es declarado se referencia como PUBLIC y en el archivo donde es llamado se referencia como
EXTRN.

Si vemos el MAPA DE MEMORIA podemos observar también que el tamaño del STACK es la suma de
ambos segmentos .STACK de cada módulo. Lo mismo sucede en el módulo .DATA

El mapa de memoria nos resulta:

Start Stop Length Name Class


00000H 00067H 00068H _TEXT CODE
00070H 00079H 0000AH _DATA DATA
0007AH 000BFH 00046H CONST DATA
000C0H 000FFH 00040H STACK STACK

Program entry point at 0000:0000


Nota: El archivo se ensambló usando TASM.

Agosto – Diciembre 2018 Pág. – 127 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

El desensamble del código resulta:

-u 0 L 36
17F9:0000 B80018 MOV AX,1800
17F9:0003 8ED8 MOV DS,AX
17F9:0005 BA0A00 MOV DX,000A
17F9:0008 B409 MOV AH,09
17F9:000A CD21 INT 21
17F9:000C BA2400 MOV DX,0024
17F9:000F B409 MOV AH,09
17F9:0011 CD21 INT 21
17F9:0013 BB0000 MOV BX,0000
17F9:0016 E81F00 CALL 0038
17F9:0019 8B1E0000 MOV BX,[0000]
17F9:001D B103 MOV CL,03
17F9:001F D3EB SHR BX,CL
17F9:0021 891E0200 MOV [0002],BX
17F9:0025 BA3A00 MOV DX,003A
17F9:0028 B409 MOV AH,09
17F9:002A CD21 INT 21
17F9:002C BB0200 MOV BX,0002
17F9:002F E80600 CALL 0038
17F9:0032 B8004C MOV AX,4C00
17F9:0035 CD21 INT 21

-u 38 66
17F9:0038 BE0400 MOV SI,0004
17F9:003B B90600 MOV CX,0006
17F9:003E C60424 MOV BYTE PTR [SI],24
17F9:0041 46 INC SI
17F9:0042 E2FA LOOP 003E
17F9:0044 B90A00 MOV CX,000A
17F9:0047 BE0800 MOV SI,0008
17F9:004A 8B07 MOV AX,[BX]
17F9:004C 3D0A00 CMP AX,000A
17F9:004F 720C JB 005D
17F9:0051 33D2 XOR DX,DX
17F9:0053 F7F1 DIV CX
17F9:0055 80CA30 OR DL,30
17F9:0058 8814 MOV [SI],DL
17F9:005A 4E DEC SI
17F9:005B EBEF JMP 004C
17F9:005D 0C30 OR AL,30
17F9:005F 8804 MOV [SI],AL
17F9:0061 8D14 LEA DX,[SI]
17F9:0063 B409 MOV AH,09
17F9:0065 CD21 INT 21

-q

Agosto – Diciembre 2018 Pág. – 128 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

3.5. Bibliotecas.

3.5.1. Introducción

Una biblioteca o librería es un archivo, normalmente con la extensión (.LIB), la cual contiene dos o más
módulos (.OBJ), estos módulos almacenan procedimientos, los cuales realizan procesos específicos, ejemplos
de procedimientos almacenados en bibliotecas son los siguientes:
 PASCAL
+ write, writeln
+ read, readln
+ ord, abs, sqr, sqrt, clrscr, gotoxy

 C
+ printf, fprintf, cprintf
+ scanf, fscanf
+ pow, gets, clrscr, gotoxy

Los módulos almacenados en las bibliotecas, se encuentran en código máquina reubicable (OBJ), son
unidos al archivo ejecutable en el momento del enlace, después de unir los módulos reubicables declarados en
la línea de comandos.

En los lenguajes de alto nivel, se proveen mecanismos para que ciertas bibliotecas (normalmente las
que contienen funciones o procedimientos de E/S y de uso común) sean llamadas de manera implícita al
realizar el enlazado.

3.5.2 LIB.EXE

El manejador de bibliotecas (LIB.EXE) nos permite reunir en un solo archivo (.LIB) módulos reubicables
(.OBJ) ya compilados o ya ensamblados con anterioridad. La ventaja de una librería es que en el momento del
enlace solo llama de la biblioteca, los procedimientos que estamos utilizando en nuestro programa.

El manejador de bibliotecas nos permite las siguientes acciones sobre una librería:
 Crear un nuevo archivo de biblioteca.
 Sumar módulos (.OBJ) a una biblioteca ya existente.
 Borrar módulos de una biblioteca.
 Remplazar módulos de una biblioteca.
 Sacar módulos de una biblioteca como archivos (.OBJ)

Sintaxis:
LIB lib_vieja [opciones] [comandos] [,arch_list] [,[lib_nuev]] [;]

Donde:
lib_vieja: Es una librería ya existente a la que se le desea hacer modificaciones. Si no existe se crea.
Si no se proporciona extensión, por default toma (.LIB)

opciones: Son alternativas usadas en la modificación o creación de una librería. Estas son las
siguientes:
/?: Ayuda en línea.
/HELP Ayuda en pantalla.
/IGNORECASE No considera Mayúsculas/Minúsculas.

Agosto – Diciembre 2018 Pág. – 129 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

/NOEXTDICITONARY No construye directorio.


/NOIGNORECASE Es sensible al tamaño.
/NOLOGO Suprime indicativo de LIB.EXE
/PAGESIZE:n Define el tamaño de página, por definición es de 16 bytes, con este
tamaño la librería más grande es de 16*65535 = 1048560 bytes.

comandos: Nos definen las acciones a realizar sobre la librería:


+ Suma un módulo a la librería.
- Borra un módulo de la librería.
-+ Reemplaza un módulo de la librería.
* Copia a un archivo .OBJ un módulo de la librería.
-* Copia a un archivo .OBJ un módulo y luego lo borra de la librería.

arch_list: Crea un archivo, el cual contiene los nombres y símbolos públicos almacenados en la librería.
Lib_nuev: Especifica un nuevo nombre para una librería, por omisión es el de lib_vieja. Cuando se
especifica este campo, el comando LIB

LIB nunca destruye la librería original, si se especifica un nuevo nombre, la crea con dicho nombre y si
no se especifica un nuevo nombre a la librería original, le cambia la extensión por BAK

Como ejemplo de uso de librerías, suponga que vamos a crear una librería que contenga ahora como
procedimientos tanto IMP.OBJ (anteriormente una MACRO, ahora convertido a procedimiento) y
BINASIB1.OBJ; ambos, en una librería llamada MILIB. Después utilizando esta librería se enlazará para formar
el archivo ENSA37.

 Archivo # 1: IMP.ASM
COMMENT * IMP.ASM Procedimiento de impresión de cadenas.

PUBLIC imp_cad
.MODEL Small

.CODE
imp_cad PROC near
mov ah, 9h ;La dirección de la cadena debe ya haber sido colocada en DX.
int 21h
ret
imp_cad ENDP
END

 Archivo # 2: BINASIB1.ASM
; Procedimiento para convertir un número del tipo Word a cadena.
PUBLIC UNO
.MODEL Small
.STACK 20h

.DATA
ascval DB 6 Dup('$')

.CODE
EXTRN imp_cad:near

Agosto – Diciembre 2018 Pág. – 130 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

uno proc near


lea si, ascval
mov cx, 6
ciclo:
mov BYTE PTR [si], 24h
inc si ;Limpia con '$' la cadena ascval
loop ciclo
mov cx, 0010 ;Pone en CX el factor de División
lea si, ascval + 4 ;Pone en SI la última dirección cc
mov ax, [bx] ;Pone en AX el contenido de bx
c20:
cmp ax, 0010 ;Valor < que 10
jb c30 ;Si lo es, SALE
xor dx, dx ;Limpia DX
div cx ;Divide por 10
or dl, 30h ;Ve a que valor corresponde
mov [si], dl ;Almacena caracter ASCII
dec si
jmp c20
c30:
or al, 30h ;Almacena último resultado
mov [si], al ;como carácter ASCII
mov dx, si
call imp_cad
ret
uno ENDP
END

 Archivo #3: Ensa34C


COMMENT * Realiza la operación A = B DIV 8*
.MODEL SMALL ;Define el modelo de memoria a usar
.STACK 20h ;Define el tamaño del STACK

.CONST
oper DB 10, 13, 'Operación: b = a DIV 8 $'
leta DB 10, 13, 'El valor de a es : $'
letb DB 10, 13, 'El valor de b es : $'
.DATA
a DW 45600 ;Define a como WORD y se inicializa.
b DW ? ;Define como WORD a b y no se inicializa.

.CODE ;Inicia el segmento de código.


EXTRN UNO:NEAR, IMP_CAD:NEAR

inicio:
mov ax, DGROUP ;Pone el inicio del segmento de datos
mov ds, ax ;en el registro DS
mov dx, offset oper
call imp_cad ;Manda a pantalla la cadena oper
mov dx, offset leta

Agosto – Diciembre 2018 Pág. – 131 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

call imp_cad ;Manda imprimir letrero para a.


lea bx, a ;Copia la dirección de a en BX.
call uno
mov bx, a ;Copia el contenido de a en BX
mov cl, 3 ;Realiza la operación de DIV
shr bx, cl ;mediante un corrimiento a la derecha de 3
mov b, bx ;Copia el contenido de BX en b
mov dx, offset letb
call imp_cad ;Manda imprimir letrero para b.
lea bx, b ;Copia la dirección de b en BX
call uno
mov ax, 4C00h ;Inicia la rutina de salida.
int 21h
END inicio

a) Usando el Macro Assembler de Microsoft


Para ensamblar cada módulo, desde la línea de comandos se usaron las siguientes instrucciones,
considerando el prompt como: C:\USER>

C:\USER>masm imp;
C:\USER>masm binasib1;
C:\USER>masm ensa34C;

A continuación como ya se tienen los archivos .OBJ se crea la librería MILIB.LIB, usando la siguiente
instrucción:
C:\USER>lib milib +binasib1 +imp, milib.lst;

Nota: Se considera que ya hay un PATH definido, y para el archivo LIB.EXE se tiene considerado su
localización en dicho PATH.
El archivo MILIB.LST contiene lo siguiente:

IMP_CAD...........IMP UNO...............BINASIB

IMP Offset: 00000010H Code and data size: 5H


IMP_CAD
BINASIB Offset: 00000090H Code and data size: 55H
UNO

Aparecen en él tanto los nombres de los módulos como el nombre de los archivos que los contienen.

Una vez que se cuenta con la librería, para enlazarla con el archivo ensa34c.obj se usa la siguiente
instrucción
C:\USER> LINK ENSA33C, ENSA37,,MILIB;

Con esto se crea el archivo ENSA37.EXE. Las comas (,,), es el lugar reservado para el archivo (.MAP).
Observe el desensamble del programa, en él se puede apreciar que fueron unidos en un solo archivo ambos
procedimientos. Sin embargo ahora imp_cad solo se adiciona una vez, y se le llama a su dirección de inicio,
cada vez que se le desea ejecutar. Esta versión fue trabajada usando el TASM. Lo que se muestra es el
segmento de código.

Agosto – Diciembre 2018 Pág. – 132 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

-u 0 L 33

17F9:0000 B80018 MOV AX,1800


17F9:0003 8ED8 MOV DS,AX
17F9:0005 BA0A00 MOV DX,000A
17F9:0008 E85900 CALL 0064
17F9:000B BA2400 MOV DX,0024
17F9:000E E85300 CALL 0064
17F9:0011 BB0000 MOV BX,0000
17F9:0014 E81D00 CALL 0034
17F9:0017 8B1E0000 MOV BX,[0000]
17F9:001B B103 MOV CL,03
17F9:001D D3EB SHR BX,CL
17F9:001F 891E0200 MOV [0002],BX
17F9:0023 BA3A00 MOV DX,003A
17F9:0026 E83B00 CALL 0064
17F9:0029 BB0200 MOV BX,0002
17F9:002C E80500 CALL 0034
17F9:002F B8004C MOV AX,4C00
17F9:0032 CD21 INT 21

-u 34 62

17F9:0034 BE0400 MOV SI,0004


17F9:0037 B90600 MOV CX,0006
17F9:003A C60424 MOV BYTE PTR [SI],24
17F9:003D 46 INC SI
17F9:003E E2FA LOOP 003A
17F9:0040 B90A00 MOV CX,000A
17F9:0043 BE0800 MOV SI,0008
17F9:0046 8B07 MOV AX,[BX]
17F9:0048 3D0A00 CMP AX,000A
17F9:004B 720C JB 0059
17F9:004D 33D2 XOR DX,DX
17F9:004F F7F1 DIV CX
17F9:0051 80CA30 OR DL,30
17F9:0054 8814 MOV [SI],DL
17F9:0056 4E DEC SI
17F9:0057 EBEF JMP 0048
17F9:0059 0C30 OR AL,30
17F9:005B 8804 MOV [SI],AL
17F9:005D 8BD6 MOV DX,SI
17F9:005F E80200 CALL 0064
17F9:0062 C3 RET

-u 64 68

17F9:0064 B409 MOV AH,09


17F9:0066 CD21 INT 21
17F9:0068 C3 RET

Agosto – Diciembre 2018 Pág. – 133 - Ing. Claudia E. Carrillo R


TECNOLOGICO NACIONAL DE MEXICO.
INGENIERIA EN SISTEMAS COMPUTACIONALES.
LENGUAJE DE INTERFAZ.

-q
Ahora veamos el archivo ENSA37.MAP

Start Stop Length Name Class

00000H 00068H 00069H _TEXT CODE


00070H 00079H 0000AH _DATA DATA
0007AH 000BFH 00046H CONST DATA
000C0H 000FFH 00040H STACK STACK

Program entry point at 0000:0000

Los tres segmentos de código, (uno por archivo), se incluyeron en uno solo llamado _TEXT. Se puede
constatar analizando el número de bytes ocupado, tanto en el desensamble como en el archivo del mapa de
memoria.

El STACK también contiene 2 segmentos, lo podemos constatar, sumando el número de bytes asignado
a cada archivo en su segmento de STACK.

Agosto – Diciembre 2018 Pág. – 134 - Ing. Claudia E. Carrillo R

También podría gustarte