Está en la página 1de 9

1

Programación estructurada
Macros
El programa macro1.asm simplemente muestra como se define la macro inicio y la utiliza en el
segmento de código. El programa macro2.asm muestra como pasar parámetros en una macro.
La macro inicie x,y,z requiere codigo,datos,pila para iniciar los segmentos correspondientes. En el
programa macro3.asm simplemente se muestra como utilizar las directivas .xall (lista solo código),
.lall (lista doto), .sall (no lista el contenido de la macro). Para ver el efecto de estas directivas el
estudiante tiene que analizar el archivo macro3.lst, que se genera en el proceso de compilación. El
programa macro4.asm muestra como se resuelve el problema que se presenta cuando en una macro
se utilizan etiquetas. Par esto se utiliza la directiva local. El programa macro5.asm muestra como
se incluye una macro externa al programa. Simplemente se utiliza la secuencia
if1
include d : macro . jas
endif

Aquí suponemos que el archivo que contiene las macros esta en d:macro.jas.

Para terminar en el programa macro6.asm se muestra como implementar el control sobre la canti-
dad de parámetros que necesita una macro para ser utilizada. Por ejemplo para dividir se necesita
el dividendo, el divisor y el cociente. Si falta uno de los parámetros, la macro no corre.

El ensamblado y el enlazado es como siempre:


masm macro5 ;
link macro5 ;

Librerías
En este caso, como ejemplo tomamos al programa libre1.asm como programa principal. Este utiliza
tres subrutinas (bopan, escribir y pocur) que no están escritas dentro del mismo programa, es decir
son externas. Para incluirlas solo es necesaria la siguiente secuencia, en el programa principal:
extrn pocur : far
extrn bopan : far
extrn escribir : far

La compilación es como sigue:


1) Ensamblado
masm libre1 ;
masm pocur ;
masm escribir ;
masm bopan ;

2) Creación de la librería jas.lib


lib jas . lib
Library does not exist . Create ? ( y / n ) y
Operations : bopan + pocur + escribir
List file : jas . lst
2

Si el estudiante quiere cambiar alguno de los módulos del sistema, basta con modificar la creación
de la librería; es decir, por ejemplo con Operations: bopan+pocur-escribir, se elimina el módulo
escribir y, por tanto, se puede cambiar

3) Enlazado
link libre1
Run File [ LIBRE1 . EXE ]:
List File [ NUL . MAP ]: libre1 . lst
Libraries [. LIB ]: jas . lib

El estudiante debe observar que al final de la línea link libre1 no se usa “;”.

Subprogramas
Para el caso de los subprogramas, el programa subpro1.asm tiene como subprograma a sub-
pro11.asm. El programa subpro2.asm tiene como subprograma a subpro21.asm. Y el pro-
grama subpro3.asm tiene el subprograma subpro31.asm.

Como ejemplo analicemos subpro3.asm y subpro31.asm.

Si abrimos subpro3.asm vemos que lo único que cambia es que al principio del programa se declaran
como externas las rutinas que vamos a utilizar. En este caso:
extrn multi : far
extrn bopan : far

Y en el subprograma subpro31.asm, cada subrrutina que queremos hacer pública, la declaramos


como tal. Por ejemplo
bopan proc far
public bopan

Es decir la rutina bopan (borra la pantalla) es pública y puede ser utilizada por cualquier otro
programa.

La creación del sistema es como sigue:

Ensamblado
masm subpro3 ;
masm subpro31 ;

Enlazado
link subpro3 + subpro31 ;

En este ultimo caso el programa principal es subpro3.

Introducción
En este programa haremos énfasis en el segmento de datos. Una buena definición de datos facilita
mucho en el diseño de los algoritmos necesarios para lograr el sistema requerido. La interfaz de la
calculadora es un conjunto de cuadrados ubicados en determinadas posiciones de la pantalla y de
3

determinados tamaños.

Un cuadrado está formado por tres tipos de lineas: ii) La línea superior es una esquina superior
izquierda (ascii 218), una o varias líneas horizontales (ascii 196) y, una esquina superior derecha
(ascii 191). ii) Las líneas intermedias son una recta vertical (ascii 179), uno o varios espacios en
blanco (ascii 20h) y, una recta vertical (ascii 179). iii) La línea inferior es una esquina inferior
izquierda (ascii 192), una o varias rectas horizontales (ascii 196) y, una esquina inferior derecha
(ascii 217). Todo esto definimos en la variable cuaDat, datos del cuadrado. Ver el listado 1

Además cada cuadrado está en una posición específica de la pantalla y, forman un conjunto que
lo definimos en la variable posCua. Por ejemplo el marco de la calculadora se ubica en la
(row,column) = (03h,0Ah), la pantallita de la calculadora está en 070Ch y la tecla de salir
está en 040Ch (al final de la variable). Fíjese que la calculadora tiene 19 items. Ver el listado 1

Cada cuadrado, también tiene un tamaño específico. Con estos, formamos un conjunto que lo defini-
mos en la variable sizCua. Por ejemplo el marco de la calculadora tiene un tamaño de (width,high)
= (16h,12h), la pantallita tiene un tamaño de 1201h, todas las demás teclas de la calculadora
tienen un tamaño de 0301h. Ver el listado 1

Finalmente, cada tecla de la calculadora tiene un número o un símbolo aritmético. Estos forman
un conjunto que lo definimos en la variable Num. Fíjese que los dos primeros elementos de Num
son 20h, 20h. Estos espacios en blanco corresponden al marco y a la pantallita de la calculadora.
Ver el listado 1

Todas las variables descritas, las utilizamos en el programa principal presentado en la figura 1.
Como se ve en el programa principal se dibuja la calculadora y se inicializa el ratón, para luego ver
el estado del ratón.

;------------------------------------------------------------------
; Segmento de datos
; -----------------
datos segment para ’ data ’
count dw 0 ; Any count , any pointer
cuaDat db 01 ,218 ,00 ,196 ,01 ,191 ; Frame ’ s data
db 01 ,179 ,00 ,032 ,01 ,179
db 01 ,192 ,00 ,196 ,01 ,217
;---------
posCua dw 030 ah ,070 ch ; Frame , screen
dw 0 a0ch ,0 a11h ,0 a16h ,0 a1bh ; keys ( row , column )
dw 0 d0ch ,0 d11h ,0 d16h ,0 d1bh
dw 100 ch ,1011 h ,1016 h ,101 bh
dw 130 ch ,1311 h ,1316 h ,131 bh
dw 040 Ch ; ( Quit )
;---------
sizCua dw 1612 h ,1201 h ; Frame , screen , keys
dw 17 dup (0301 h ) ; Width and High
;---------
Num db 20 h ,20 h , ’789/456*123 -0.=+ X ’
;---------
myName db ’ JaS -2021 ’ ,24 h
4

aString db 10 dup (?) ,24 h ; Any string to print


datos ends
;------------------------------------------------------------------

Listado 1: Segmento de datos

Programa principal
Como se ve en la figura 1, en BX están las teclas del ratón, por tanto si BX = 1 (tecla izquierda)
llamamos a la rutina moKey. Esta rutina permite determinar, sobre que tecla de la calculadora se
hizo click, en caso de hacer click sobre la tecla X se sale del sistema que implementa la calculadora.

call inFace ; Draws up the interface


call iMouse ; Initializes the mouse
otro : mov ax ,3 ; Mouse status , CX = Col , DX = row
int 33 h ; B2 = Middle , B1 = Right , B0 = Left
cmp bx ,1 ; If left click
jne otro
call moKey ; Get a number of a key
call kBoard ; Check the keyboard values
cmp al , ’X ’ ; If click on ’X ’
jne otro
mov ax ,2 ; Hide the mouse cursor
int 33 h
ret

Figura 1: Programa principal e interfaz de usuario

Dibujo de la calculadora
En primer lugar se explicará como se diseñó la interfaz de la calculadora, como se ve en la figura
1. Posteriormente analizaremos como funciona la lectura de datos utilizando el teclado de la calcu-
ladora y el ratón.

En la figura 2 se muestra la rutina para dibujar la caratula de la calculadora en una pantalla 80x25.
Se empieza borrando la pantalla e inicializando variables y punteros. No olvide que la calculadora
tiene, count = 19, items. Luego dibujamos 19 cuadrados. Cada cuadrado esta en la posición dx
= posCua[si] y tiene un tamaño cx = sizCua[si].
5

inFace

bopan
count ← 19
si ← 0
di ← 0
inF1:
inFace proc
dx ← posCua[si] call boPan ; Clears up the screen
mov count ,19; Number of items in calculator
cx ← sizCua[si] mov si ,0
cuadro mov di ,0
inF1 : mov dx , posCua [ si ]; Position of each square
mov cx , sizCua [ si ]; Size of each square
dx ← posCua[si] call cuadro
dx ← dx + 0102h mov dx , posCua [ si ]
add dx ,0102 h ; Position of each number
poCur call pocur
al ← Num[di] mov al , Num [ di ]
cx ← 1 mov cx ,1
call puChar
puChar inc si
inc si
inc di
si ← si + 2 dec count
jnz inF1
mov dx ,0514 h
di ← di + 1 lea si , myName
call wrStri
ret
count ← count - 1 inFace endp

no
count = 0
yes

dx ← 0514h
si ← myName
wrStri

ret

Figura 2: Dibuja la calculadora

Posteriormente colocamos el valor de la tecla (un número o un símbolo aritmético). Este valor está
en al = Num[di] y se ubica en la posición dx = dx + 0102h. En seguida se apunta a siguiente
cuadro si = si + 2 y su valor di = di + 1. Para terminar bautizamos la calculadora en la posición
dx = 0514h.
6

cuadro

poCur
bx = cuaDat
byte ptr[bx+02] ← ch
cuadro proc
byte ptr[bx+08] ← ch call pocur
byte ptr[bx+14] ← ch lea bx , cuaDat
mov byte ptr [ bx +02] , ch ; Width
ch ← 0 mov byte ptr [ bx +08] , ch
linea mov byte ptr [ bx +14] , ch
xor ch , ch ; High
call linea
bx ← bx + 6 add bx ,6 ; next line
Cu01:
cu01 :
inc dh
dh ← dh + 1 call pocur
poCur call linea
loop cu01
linea add bx ,6
inc dh
no call pocur
cx = 0 call linea
yes
ret
cuadro endp
bx ← bx + 6
dh ← dh + 1
poCur
linea

ret

Figura 3: Esta rutina dibuja cada item de la calculadora

Continuamos con la explicación del dibujo de la caratula de la calculadora. En la figura 2 se


ve que cada cuadrado se dibuja en una posición DX = Row,Column y de un tamaño CX =
Width,High.

En la figura 3 se ve la rutina que dibuja un cuadro en la posición dada por DX y del tamaño dado
por CX. En las direcciones 02 (fila superior), 08 (filas intermedias) y 14 (fila inferior) de la variable
cuaDat determinamos el ancho de cada cuadrado. Luego limpiamos CH para tener el CX = High.

Fíjese que la rutina cuadro dibuja tres líneas. La primera línea con los datos de la dirección BX
= 0, la segunda línea en la dirección BX = BX + 6 y, la tercera línea en la dirección BX =
BX + 12, de la variable cuaDat. Por otro lado la rutina linea dibuja una línea que consiste en:
una esquina izquierda (superior e inferior), líneas horizontales o espacios en blanco y una esquina
derecha (superior e inferior). No olvide que los datos de cada línea están definidos en la variable
BX = cuaDat. Para la rutina, linea, ver el programa principal

linea proc
push cx
push dx
7

mov cl ,[ bx +0]
mov al ,[ bx +1]
call puChar ; left corner ( up , low )
add dl , byte ptr [ bx +0]
call poCur
mov cl ,[ bx +2]
mov al ,[ bx +3]
call puChar ; between corners ( lines and white spaces )
add dl , byte ptr [ bx +2]
call pocur
mov cl ,[ bx +4]
mov al ,[ bx +5]
call puChar ; right corner ( up , low )
pop dx
pop cx
ret
linea endp

Listado 2: Rutina para dibujar una línea

El código para dibujar una línea está en el listado 2. Antes de empezar, no olvide que DX =
posCua, CX = sizCua y BX = cuaDat. Por ejemplo para dibujar la parte superior de la
caratula de la calculadora. Vea que en las direcciones [BX + 0] y [BX + 1] están los datos
para dibujar la esquina superior izquierda CL = 1 y AL = 218, lo escribimos (puChar) y luego
incrementamos la columna DL = DL + [BX+0], en esa posición de pantalla dibujamos CL =
16h veces AL = 196, es decir 22 lineas horizontales y, luego incrementamos la columna DL = DL
+ [BX+2]. Terminamos la línea dibujando la esquina superior derecha CL = 1 y AL = 191,
estos datos están en las direcciones [BX + 4] y [BX + 5].

Teclado utilizando el ratón


En las figuras 4 y 5 se muestra como se ha implementado la lectura de datos utilizando el puntero
del ratón sobre la caratula de la calculadora.

En la figura 4 vemos como se capturan los números y símbolos aritméticos utilizando el puntero del
ratón. Para esto sirve la rutina moKey (teclado con ratón). Si se analiza la variable posCua, en el
listado 1, las posiciones del los items que forman la calculadora, ocupan las posiciones de memoria
posCua[0000] a posCua[0036], es decir inicializamos count = 36 y los punteros si = 4 (menos el
marco y la pantallita) y di = 2. A continuación, el cursor del ratón (CX y DX) los convertimos a
AX = Row,Column. La información en AX, se compara con cada posición de cada tecla de la
calculadora. Una tecla está entre su esquina superior izquierda (BX) y su esquina inferior derecha
(CX = CX + 0204h). Si se hace click sobre una tecla, se obtiene en AL el número o símbolo
aritmético de la tecla (al = Num[di]) y termina el programa. Si se hace click fuera de una tecla,
simplemente se incrementan los punteros si = si + 2 y di = d1 + 1 y, cuando se llega al final de
la variable posCua, se termina el programa si ≤ count.
8

moKey

count ← 36
si ← 4
di ← 2
moKey proc
ax ← cx mov count ,36; Number of keys in calulator
mov si ,4 ; Point to the upper left corner
cx ← 3 mov di ,2 ; Point to the key number
shr ax,cl mov ax , cx
mov cx ,3
shr dx,cl shr ax , cl ; Column
xchg dh,dl shr dx , cl ; Row
ax ← ax or dx xchg dh , dl
Mo1: or ax , dx ; AH = Row , AL = Column of mouse
Mo1 : mov bx , posCua [ si ]; Upper left corner
mov cx , bx
bx ← posCua[si] add cx ,0204 h ; Lower right corner
cx ← bx cmp al , bl ; BL <= AL <= CL
cx ← cx + 0204h jb Mo2
cmp al , cl
ja Mo2
no Mo2:
al ≥ bl cmp ah , bh ; BH <= AH <= CH
yes jb Mo2
cmp ah , ch
no
al ≤ cl ja Mo2
mov al , Num [ di ]; Get the number of a key
yes
jmp Mo3
no Mo2 : inc si
ah ≥ bh inc si
yes inc di
no cmp si , count
ah ≤ ch jbe Mo1
yes Mo3 : ret
moKey endp
si ← si + 2
al ← num[di]
di ← di + 1
no
si ≤ count
yes
ret Mo3:

Figura 4: Esta rutina ve sobre que tecla de la calculadora se hizo click

En la figura 5 se implementa la rutina para verificar si se hizo click sobre una de las teclas de la
calculadora: X + - * / = 1 2 3 4 5 6 7 8 9 0 ..

En este programa hay que observar dos aspectos. Hay símbolos imprimibles, las teclas 0 1 2 3 4
5 6 7 8 9 . y los símbolos funcionales, las teclas + - / * =. Los símbolos de funciones pueden o
no ser imprimidos.

Para terminar simplemente indicamos que los procedimientos myAdd, muSub, myMul, MyDiv
y MyResul se dejan para que el estudiante las implemente. La calculadora lee los datos en la
misma posición de la pantallita. Esto también tendrá que modificar el estudiante.
9

kBoard proc
cmp al , ’X ’
je kb7
cmp al , ’+ ’
kBoard je kb1
cmp al , ’ - ’
si je kb2
al = ‘X’ cmp al , ’* ’
no je kb3
kb1:
yes cmp al , ’/ ’
al = ‘+’ myAdd je kb4
no cmp al , ’= ’
kb2:
yes je kb5
al = ‘-’ mySub cmp al , ’0 ’ ; If 0 <= AL <= 9
no
kb3: jb kb6 ; then
yes cmp al , ’9 ’ ; copy AL to aString
al = ‘*’ myMul ja kb6 ; to write
no
kb4: kb0 : mov aString [0] , al
yes call myAdd
al = ‘/’ myDiv jmp kb7
no
kb5: kb1 : call myAdd
yes jmp kb7
al = ‘=’ myResul kb2 : call mySub
no jmp kb7
no kb6: kb3 : call myMul
al ≥ ‘8’ jmp kb7
yes kb4 : call myDiv
no no jmp kb7
al ≤ ‘9’ al = ‘.’ kb5 : call myResul
yes jmp kb7
kb6 : cmp al , ’. ’
ret je kb0
kb7 : ret
kBoard endp

Figura 5: Esta rutina permite seleccionar solo los símbolos: X + - * / = 1 2 3 4 5 6 7 8 9 0 .

Proyecto
En base al programa calc06.asm, diseñar un sistema de computación, utilizando programación
estructurada. Para esto el estudiante debe revisar el capítulo C06.Pr.Estruc. El sistema de com-
putación debe implementar una calculadora que lea los datos y símbolos aritméticos con el cursor
del ratón o el teclado y, realice las cuatro operaciones aritméticas con números enteros. Es decir el
estudiante debe implementar las rutinas myAdd, mySub, myMul, myDiv y myResul.

Fecha de entrega
Viernes 8 de abril de 2021, máximo hasta las 23:00, al correo javisanabria@gmail.com. Enviar solo
el código fuente y el informe

También podría gustarte