PRÁCTICA 10 USO DE MENÚS PARA MODIFICAR ARCHIVOS DE CONFIGURACIÓN 1 INTRODUCCIÓN Esta práctica ayudará a familiarizarse con el uso de menús, para modificar archivos de configuración. La implementación de diferentes rutinas para salvar, hacer y recuperar ventanas. 2 OBJETIVOS 2.1 El alumno aprenderá a usar rutinas que permiten salvar una ventana, o crearla o recuperarla 2.2 Aprenderá a alternar archivos, usando menús, que contengan parámetros de operación de un programa, que esté en el momento de su ejecución. 2.3 Aprenderá a crear y ensamblar un programa residente que salve el contenido de una pantalla en modo alfanumérico de video. 3. DESARROLLO 3.1 Capturar y ensamblar el siguiente módulo con el nombre VENTANA.ASM. %TITLE RUTINAS PARA VENTANAS Y MENÚS IDEAL MODEL small rc EQU 13 ASCII del orno de carro nl EQU 10 ASCII de nueva línea DATASEG PUBLIC color,colornormal ancho db 0 ancho de la ventana alto db 0 altura de la misma SupIzq dw 0 coordenadas de vértice superior izquierdo InfDer dw 0 ídem para vértice superior derecho resto dw 0 La estructura de datos se construye con la siguiente información número de elementos, columna, renglón, tamaño de los elementos elemento inicial, cadena con complementos, 0 10-1
MenuLetras db 4,14,14,1,1, A\E\I\M\,0 No. Elementos, col, ren, long, ítems color db 0 ColorNormal db 1fh ColorGets db 2eh Nitems db 0 PalabraCfg db 0 seleccion db 0 ColorSelec db 30 CODESEG De CADENA.OBL EXTRN SacaCadena:proc,LeeCadena:proc De Cursor EXTRN De Pag4 EXTRN PUBLIC Cursi:near,CursorDer:near BorraPan:near SalvaVentana,HaceVentana,DespMenu,menú,RecupVentana %NEWPAGE EscrCarX EXHIBE UN CARÁCTER Y SU ATRIBUTO DE COLOR USANDO EL BIOS Entrada: AL con el ASCII del carácter a exhibir variable color con el byte de atributo Salida: Ninguna (sólo exhibe en página 0) Registros: Ninguno PROC EscrCarX push ax bx cx salva registros mov ah,9 llamada para imprimir carácter/atributo mov bh,0 Asigna página 0 mov cx,1 escribe solamente un carácter mov bl,[color] trae color int 10h escribe el carácter y el atributo callcursorder pop cx bx ax recobra registros ENDP EscrCarX ahora mueve el cursor a la siguiente posición Espera Entrada: :Salida: Registros: RUTINA QUE ESPERA A QUE SE OPRIMA UNA TECLA. FIN SI ES ESC Ninguna Ninguna, aunque termina el programa con la tecla ESCAPE Ninguno PROC Espera push ax Salva AX mov ah,0 función del BIOS para esperar teclazo 10-2
int 16h cmp al,27 se dio ESCAPE? je @@10 si, brinca pop ax recobra AX mov ax,4c00h regresa a DOS int 21h ENDP HaceVentana DIBUJA UNA VENTANA CON BASE EN UNA LISTA DE PARÁMETROS Entrada: CH, CL = (fila, columna) de vértice superior izquierdo DH, DL = (fila, columna) de vértice inferior derecho DI apunta a lista de parámetros Salida: Ninguna (exhibe ventanas) Registros: Ninguno PROC HaceVentana push ax bx cx dx salva registros mov [SipIzq],cx salva coordenadas mov [IngDer],dx Salva coordenadas mov [ancho],dl Calcula ancho de la ventana sub [ancho],cl resta columna izquierda dec [ancho] ajusta mov [alto],dh hace lo mismo para la altura sub [alto],ch resta fila superior dec [alto] ajusta mov dx,[supizq] mov bl,[di+9] trae color de la ventana mov bh,0 página 0 mov ah,9 función del BIOS para sacar carácter mov al,[di] trae carácter esquinero mov cx,1 una vez call CuXY posiciona el cursor int 10h CadVentana call CursorDer mueve el cursor mov al,[di+1] trae carácter para tope superior mov cl,[ancho] trae número de veces int 10h llama al BIOS mov dx,[supizq] DH = columna superior mov dl,[byte ptr InfDer] DL = fila derecha call CurXY se posiciona en esquina mov al,[di+2] trae carácter esquinero mov cx,1 una vez int 10h mov al,[di+7] trae cara para marco vertical inc dc ajusta fila mov dl,[byte ptr SupIzq] DL = columna izquierda call CurXY se posiciona int 10h exhibe carácter call CursorDer 10-3
mov al,[di+8] trae carácter de relleno push cx salva número de veces mov cl,[ancho] trae ancho int 10h pone relleno pop cx mov al,[di+3] trae carácter para marco mov dl,[byte ptr InfDer] trae columna call CurXY pone cursor int 10h saca marco call CusorDer mueve cursor mov al, trae sombreador push bx mov bl,08 gris int 10h pop bx dec [alto] terminó con parte media? jnz @@10 no, regresa mov dx,[infder] DH = fila inferior mov dl,[byte prt SupIzq] trae columna izquierda mov al,[di+6] trae esquinero inferior derecho call CurXY int 10h y lo exhibe call CursorDer mov al,[di+5] trae carácter de la base mov cl,[ancho] trae número de veces int 10h saca la base de la ventana inc dl inc dh call CurXY pone cursor mov al, trae sombreados push bx mov bl,08 gris int 10h pop bx mov dx,[infder] call CurXY mov al,[di+4] tare carácter esquinero inferior derecho mov cx,1 una vez int 10h call CusorDer mov al, trae sombreador mov bl,08 gris int 10h pop dx cx bx ax recupera registros ENDP HaceVentana SalvaVenta GUARDA CONTENIDO ORIGINAL DE LA VENTANA Entrada: CH, CX = (fila, columna) de vértice superior izquierdo DH, DL = (fila, columna) de vértice inferior derecho DI apunta al área para salvar contenido Salida: Área de la memoria con contenido de RAM de video Registros: Ninguno 10-4
PROC SalvaVentana push ax cx dx es si ds salva registros mov [SupIzq],cx salva coordenadas mov [InfDer],dx salva coordenadas mov [ancho],dl calcula ancho sub [ancho],cl resta columna izquierda inc [ancho] ajusta por marco y inc [ancho] sombra mov [alto],dh calcula altura sub [alto],ch resta fila superior inc [alto] ajusta por marcos y inc [alto] sombra mov ax,80 ancho de la pantalla sub al,[ancho] resta ancho shl ax,1 por 2 mov [resto],ax salva resto mov axm0b800h apunta el segmento de RAM para video mov ds,ax lo pone en DS mov ax,@data trae segmento original de datos mov es,ax lo pone en ES xor bx,bx BH = 0 xor ax,ax AH = 0 mov al,ch AL = fila superior mov bl,80 BL = ancho de pantalla mul bl mov bl,cl trae columna izquierda add ax,bx suma a dirección previa shl ax,1 por 2 mov si,ax arma registro fuente xor ch,ch CH = 0 cld incrementando mov cl,[es:ancho] suma contador rep movsw mueve caracteres y sus atributos add si,{es:resto] agrega los que ya no salva dec [es:alto] terminó? jnz @@10 no, brinca pop ds si es dx cx ax recupera ENDP SalvaVentana :RecupVentana DIBUJA EL CONTENIDO SALVADO ANTES DE UNA VENTANA Entrada: CH, CX = (fila, columna) de vértice superior izquierdo DH, DL = (fila, columna) de vértice inferior derecho SI apunta a área de memoria donde se salvó la ventana Salida: Área de RAM de video queda actualizada Registros: Ninguno PROC RecupVentana push ax cx dx es ds si salva todo mov [SupIzq],cx salva coordenadas mov [InfDer],dx salva coordenadas 10-5
mov [ancho],dl calcula ancho sub [ancho],cl resta columna izquierda inc [ancho[ ajusta marcos y inc [ancho] sombra mov [alto],dh calcula altura sub [alto],ch resta fila superior inc [alto] ajusta marcos y inc [alto] sombra mov ax,80 ancho de la pantalla sub al,[ancho] resta ancho shl ax,1 por 2 mov [resto],ax salva bytes no salvados por fila mov ax,0b800h carga segmento de RAM de video mov es,ax lo pone en AS xor bx,bx BH = 0 xor ax,ax AH = 0 mov al,ch trae fila superior mov bl,80 pone ancho mul bl mov bl,cl trae columna izquierda add ax,bx suma a cantidad de caracteres shl ax,1 por 2 (para incluir atributo) mov di,ax arma registro de destino xor ch,ch arma contador cld pone auto incremento mov cl,[ancho] arma contador rep movsw mueve caracteres y sus atributos add di,[resto] agrega lo caracteres no salvados dec [alto] terminó? jnz @@10 no, brinca pop si ds es dx cx ax recupera todo RecupVentana ENDP DespMenu Entrada: Salida: Registros: EXHIBE UN MENÚ CON BASE EN UNA LISTA DE PARÁMETROS SI apunta a lista de parámetros de menú Exhibe el menú especificado Ninguno PROC DespMenu push ax cx dx si salva cld auto incrementa lodsb mov cl,al lo pone en CL lodsw mov dx,ax y salva en DX call CurXY posiciona cursor xor ch,ch arma contador inc si ajusta apuntador lodsb mov [selección],al salva valor trae cantidad de ítems trae fila y columna trae número de ítem preseleccionado 10-6
mov bh,0 inicializa @@5: inc bh cmp [selección],bh jne @@6 mov al,[coloselec] trae color para marcado mov color,al lo salva mov al,16 trae carácter para marcado call EscrCarX lo exhibe mov al, seguido de espacio call EscrCarX jmp @@6: mov al,[colornormal] trae color normal mov [color],al lo salva mov al, pone espacios (para borrar) call EscrCarX call EscrCarX lodsp trae carácter del ítem cmp al, \ es el separador? je @@20 si, brinca call EscrCarX lo exhibe jmp @@10 continua @@20: inc dh otra fila call urxy pone cursor loop @@5 hasta agotar ítems pop si dx cx ax recobra todo ENDP DespMenu Menu Entrada: Salida: Registros: ESPERA TECLA DE FLECHA Y ENTER PARA PROCESAR UN MENÚ SI apunta a parámetros del menú Modifica un parámetro de la lista de un menú (selección) Ninguno PROC Menu push ax cx dx si Salva registros cld auto incrementa lodsb trae cantidad de ítems mov [Nitems],al lo salva lodsw trae posición del menú mov dx,ax lo pone en DX lodsb trae largo de ítems xor ch,ch arma contador mov cl,al add I,2 ajusta lodsb trae ítem seleccionado mov bh,al lo pone en BH dec dh decrementa fila superior add dh,bh agrega ítem seleccionado 10-7
call CurXY pone cursor mov al,16 trae carácter de marcado call EscrCarX lo exhibe call CurXY repone cursor mov l,[colorgets] trae color de resaltado mov [color],al lo salva call EscrNatrib2 cambia atributo @@20: call EsperaTecla2 espera teclazo cmp al,13 se dio ENTER? je @@50 con ENTER, salir cmp al,0 nada llegó? jne @@20 nada, salta cmp ah, M flecha derecha? je @@30 sí, salta cmp ah, P flecha abajo? je @@30 sí, salta cmp ah, K flecha izquierda? je @@40 sí, salta cmp ah, H flecha arriba? je @@40 sí, salta jmp @@20 @@30: call PintaElec cambia atributo cmp bh,[nltems] estaba en el fondo? jne @@35 no, brinca mov bh,1 inicia selector sub dh,[nltems] inicia fila inc dh ajusta jmp @@10 @@35: inc bh incrementa selector inc dh incrementa fila jmp @@10 @@40: call PintaElec cmp bh,1 ya estaba arriba? jne @@45 no, brinca mov bh,[nltems] pone selector add dh,[nltems] pone fila de dec dh fondo jmp @@10 @@45: dec bh decrementa selector dec dh y fila jmp @@10 @@50: pop si recobra apuntador mov [si+4],bh actualiza parámetro de ítem seleccionado pop dx cx ax recupera ENDP Menu 10-8
PintaElec BORRA MARCADOR Y REPONE ATRIBUTO EN ÍTEM Entrada: DX con posición del ÍTEM CX con largo del ÍTEM Salida: Cambia el atributo de un ÍTEM Registros Ninguno PROC PintaElec mov al,[colornormal] trae color normal mov [color],al lo salva mov al, espacio para buscar call CurXY pone cursor call EscrCarX pone espacio call CurXY repone cursor call EscrNatrib2 cambia atributo de color ENDP PintaElec PROC EsperaTecla2 mov ah,1 int 16h jz @@10 mov ah,0 int 16 ENDP EsperaTecla2 PROC EscrNAtrib2 push ax bx cx salva registros CX = N mov bh,0 página cero mov bl,[color] trae atributo mov ah,8 función para leer carácter y atributo int 10h del BIOS push cx salva N o menos mov cx,1 una vez mov ah,9 función para sacar atributo y carácter int 10h del BIOS pop cx trae cantidad call CursorDer mueve cursor loop @@10 lo hace N veces pop cx bx ax recobra ENDP EscrNAtrib2 END 3.2 Capturar el programa y salvarlo como en MENUS.ASM. Ensamblarlo y hacerlo ejecutable mediante: C:\SEM386>tasm /zi menus C:\SEM386>tlink /v menus,,,rem 10-9
%TITLE CAMBIA CONFIGURACIÓN PARA OTROS PROGRAMAS IDEAL DOSSEG MODEL small STACK 512 Programa MENUS.ASM ensamblarlo y ligarlo con: tasm /zi menus tlink /v menus,,,rem rc EQU 13 ASCII del orno de carro nl EQU 10 ASCII de nueva línea DATASEG EXTERN ColorNormal:byte, color:byte Letra db A letra a usar en caso de error Numero db 3 número a usar en caso de error CadVentana db í À,1fh CadSalVent db 2048 dup (0) área para salvar ventana original cadena1 db Letra May,0 cadena2 db Número de color,0 La estructura de datos se construye con la siguiente información: Número de elementos, columna, renglón, tamaño de los elementos, elemento inicial, cadena con elementos,0 MenuLetras db 4,14,14,1,1, A\E\I\M\,0No. elem, col, ren, long, ítems MenuNumeros db 3,24,14,1,1, 3\5\7\,0 MenuDatos db 2,48,08,2,1, 7\8\ 0 MenuBits db 3,36,08,4,1, UNO\DOS\TRES\,0 MenuPuertos db 2,12,15,5,1, COM1:\COM2:\,0 PalabraCfg db 0 config db A3121 ArchCfg db CONFIG.TXT,0 cadena ASCIIZ HandCfg dw 0 CODESEG De TECLADO.OBJ EXTRN EsperaTecla:proc,TraeCar:proc De ERRDISCO EXTRN ErrDisco:proc De CADENAS.OBJ EXTRN SacaCadena:proc,LeeCadena:proc De Cursor EXTRN CurXY:near,CursorDer:near 10-10
De Pag4 EXTRN De Ventana EXTRN BorraPan:near SalvaVentana:proc,HaceVentana:proc,RecupVentana:proc Inicia: mov ax,@data mov es,ax mov ds,ax call LeeCnfig abre archivo de configuración y lo lee mov al,[colornormal] trae color mov [color],al lo salva mov cx,0a0ah define vértice superior izquierdo mov dl,60 define otro vértice mov dh,20 mov di,offset CadSalVent apunta al área para salvar call SalvaVentana salva ventana original mov di,offset CadVentana apunta a parámetros call HaceVentana dibuja la ventana mov dx,0c0ch define posición de cadena de 1er. menú call CurXY coloca ahí el cursor mov di,offset cadena1 apunta a cadena call SacaCadena exhibe dicha cadena mov si,offset MenuLetras apunta a parámetros de menú de letra call DespMenu lo exhibe mov dx,0c16h repite lo anterior call curxy mov di,offset cadena2 para cadena de 2do. Menú call SacaCadena mov si,offset MenuNumeros y el menú de números call DespMenu mov si,offset MenuLetras apunta a parámetros del menú de letras call menú el usuario elige uno de ellos mov si,offset MenuNumeros lo mismo para el menú de números call menú call EscrCnfig escribe cambios en archivo CONFIG.TXT mov cx,0a0ah redefine vértice superior izquierdo mov dl,60 e inferior derecho mov dl,20 mov si,offset CadSalVent apunta al área donde salvó call RecupVentana repone contenido original Salir: mov ah,04ch función de DOS: termina el programa mov al,0 regresa código de salida int 221h 10-11
%NEWPAGE Espera Entrada: Salida: Registros. RUTINA QUE ESPERA A QUE SE OPRIMA UNA TECLA. FIN SI ES ESCAPE Ninguna Ninguna, aunque termina el programa con la tecla ESCAPE Ninguno PROC Espera push ax salva AX mov ah,0 función del BIOS para esperar teclazo int 16h cmp al,27 se dio ESCAPE? je @@10 sí, brinca pop ax recobra AX mov ax,4c00h regresa a DOS int 21h ENDP Espera PROC mov int jz mov int ENDP EsperaTecla2 ah,1 16h @@10 ah,0 16h EsperaTecla2 PROC EscrNAtrib2 push ax bx cx mov bh,0 mov bl,[color] mov ah,8 int 10h push cx mov cx,1 mov ah,9 int 10h pop cx call CursorDer loop @@10 pop cx bx ax ENDP EscrNAtrib LeeCnfig Entrada: Salida: Registros: ABRE EL ARCHIVO DE CONFIGURACIÓN Y LO LEE Ninguna Ninguna Ninguno 10-12
PROC LeeCnfig push ax bx cx dx si salva registros mov dx,offset ArchCfg apunta a cadena ASCIIZ mov ah,3dh para abrir archivo mov al,40h modo normal int 21h abre el archivo jc @@10 salta si no pudo mov [HandCfg],ax salva handle mov ah,3fh para leer archivo mov bx,[handcfg] trae handle mov cx,2 lee dos bytes mov dx,offset config apunta al área de salvar int 21h lee el archivo jc @@20 salta si no pudo mov al,[config] calcula número de selección sub al, A resta inferior shr al,2 /4 inc al ajusta mov [MenuLetras+4],al lo pone en cadena de menú mov al,[config+1 hace lo mismo para segundo menú sub al, 3 resta inferior shr al,1 /2 inc al ajusta mov [MenuNumeros+4] lo salva en su cadena mov ah,3eh la función para cerrar archivo mov bx,[handcfg] usando el handle int 21h con DOS jmp @@20 hace proceso dummy mov ah,3ch función para crear archivo mov cx,00h normal mov dx,offset ArchCfg apunta a cadena ASCIIZ int 21h crea archivo jc @@20 brinca si no pudo mov [Handfg] salva handle mov al,[letra] le escribe parámetros por omisión mov [config],al pone A mov al,[numero] y 3 mov [config+1 mov ah,40h función para escritura mov bx,[handcfg] con handle mov cx,2 dos caracteres mov dx,offset config apunta al área int 221h escribe en el archivo mov ah,3eh función para cerrar archivo mov bx,[handcfg] trae handle int 21h invoca a DOS @@20: call FormaPal llama a rutina dummy pop si dx cx bx ax ENDP LeeCnfig 10-13
EscrCnfig Entrada: Salida: Registros: ESCRIBE EL ARCHIVO DE CONFIGURACIÓN El parámetro de selección de cada lista de menú El área de memoria para salvar la configuración Ninguno PROC EscrCnfig push ax bx cx dx si salva todo mov al,[menuletras+4] trae número de ítem elegido dec al lo decrementa shl al,2 por 4 add al, A lo hace letra mov [config],al salva en área de config mov al,[menunumeros+4] hace lo mismo para siguiente menú dec al decrementa shl al,1 por 2 add al, 3 lo hace dígito decimal en ASCII mov [config+1],al lo salva mov dx,offset ArchCfg apunta a cadena ASCIIZ mov ah,3dh para abrir archivo mov al,02h modo normal int 21h abre el archivo jc @@10 brinca si hay error @@5: mov [HandCfg],ax salva handle mov ah,40h función para escribir mov bx,[handcfg] trae handle mov cx,2 dos caracteres mov dx,offset config apunta a mensaje a escribir int 21h escribe en el archivo jc @@20 brinca si no pudo mov ah,3eh función para cerrar archivo mov bx,[handcfg] trae handle int 21h llama a DOS jmp @@20 mov ah,3ch para crear un archivo mov cx,0000h normal int 21h crea archivo jc @@20 brinca si no puede jmp @@5? call FormaPal rutina dummy pop si dx cx bx ax ENDP EscrCnfig 10-14
FormaPal Entrada: Salida: Registros: RUTINA PARA UN PROCESO EXTRA Ninguna Ninguna Ninguno PROC ENDP FormaPal Aquí puede ir una rutina más compleja para formar la configuración FormaPal END Inicia fin del programa MENUS.ASM 3.3 Ejecutar el programa MENUS y observar cómo modifica el archivo CONFIG.TXT y ver si preserva el contenido original de la ventana. Se muestran dos ejemplos de corrida del programa MENUS. Correrlo con diferentes contenidos de CONFIG.TXT y también sin que éste exista. Atributos para caracteres: Filas = fondo, columnas = frente Primer carácter es oscuro, el segundo brillante 00 01 02 03 04 05 06 07 00 EE EE EE EE EE EE EE EE 01 EE EE EE EE EE EE EE EE 02 EE EE EE EE EE EE EE EE 03 EE EE EE EE EE EE EE EE 04 EE EE EE EE EE EE EE EE 05 EE EEÍ Ă 06 EE EE 07 EE EE letra May Num de color Línea en b A 3 E 5 Línea en c I 7 M Línea en v Línea en n Esta línea debe estar parpadeando en color 7 C:\SEM386>menus 10-15
ABCD.MAP ABCD.EXE DIRE.OBJ SONIDO.OBJ RATON.ASM RATON.OBJ RATON.MAP RATON.EXE DIRE.ASM SONIDO.MAP SONIDO.EXE ROJA.ASM ROJA.OBJ ROJA.OBJ ROJA.MAP ROJA.EXE ALERTA.~ ALERTA.ASN DIREC.OBJ DIREC.MAP DIREC.EXE LIB.TXT DIRECL.ASM DIRECTL.OBJ PONECAD.~AS DIREC.~AS CALCAZO DIRE.MAP DIRE.EXE PANA.CFG PONECAD.ASM DIREC.TXT CALCA.OBJ CALCA.MAP CALCA.EXE DIRW.ASM TABAS.ASM TASC.~TX RASC.TXT TASC.OBJ TASC.MAP ERRDISCO.ASM ERRDISCO.OBJ MENUS.ASM CUADRO.OBJ CUADRO.MAP CUADRO.EXE ALEGRIA.ASM ALEGRIA.OBJ ALEGRIA.MAP ALEGRIA.EX PANTALLA.EXE VIDEO.ASM PANTALLA.EXE CNFIG.OBJ Letra May Num de color CONFIG.~TX PAG4.OBJ CURSOR.OBJ MENUS.OBJ A 3 SALIDA.PRN [HOLZNER] E 5 [MEMUT] LPT2FILE.E I 7 LPT2FILE.MAP MACDOS.ASM SALIDA.PRI [CORTES] FECHESPEXE RELOJ.COM RELOJ.MAP 225 VENTANA.OBJ C:\menus 4. TAREAS 4.1 Agregar al módulo VENTANA.ASM rutinas del MOUSE que permitan elegir un ítem de un menú con el clic del botón izquierdo del mismo. 4.2 Modificar MENUS.ASM para subir un poco la ventan y agrandarla un poco y agregar procesamiento para los menús de puerto y de baudios. 4.3 Escribir un programa tipo COM llamándolo FOTO.ASM que se pueda dejar residente y que salve el contenido de una pantalla alfanumérica en el archivo XX.TXT (sobrescribiendo) si se usan las teclas Alt-Mayús Izq. El programa debe evitar su reinstalación y debe poder ser desinstalarlo con el comando: FOTO /C 10-16