Problemas de Programación en Ensamblador 80x86 (entorno DOS)

Anuncio
Problemas de Programación en Ensamblador 80x86 (entorno DOS).
Técnicos en Computación e Informática.
Listado 3.1.- Proponer un programa que permita indicar con un Aclick@ del ratón un primer punto en pantalla
(X1, Y1). Luego se procede a indicar un segundo punto en la pantalla (X2, Y2) también mediante
un Aclick@ de ratón (ver *). Estando definidos estos dos puntos, el area definida por la diagonal cuyos
extremos son esos puntos, cambia de atributo. Por simplicidad, suponga que X1 < X2, e Y1 < Y2.
Ver figura en página siguiente.
Comentarios y ayudas:
Se sugiere definir variables en memoria para guardar las parejas de coordenadas. A partir de éstas puede
comparar, calcular la cantidad de columnas e hileras, etc...
Lo mejor resultará trabajar con coordenadas en 80x25 (texto normal) en lugar de 640x200. Para ello puede
dividir sus coordenadas por 8, división que siempre dará lugar a una cantidad par. La división con
instrucciones 80x86 puede realizarse de alguna de las formas que se indican en a) y b) siguientes (**). Además
recuerde que tiene una rutina que transforma X,Y en Offset de memoria de Video.
(*) Existe una situación especial que debe atender. Lo razonable es elaborar un programa que realiza dos
lecturas sucesivas del estado del botón del ratón (ax=03H, int 33H), una para el primer Aclick@ y la otra para
el segundo Aclick@. Sin embargo, como el tiempo de ejecución de las instrucciones es sumamente bajo (nivel
de nanosegundos), y siendo el tiempo en que se mantiene presionada la tecla mucho más alto (micro y
milisegundos) que el tiempo de ejecución de instrucciones, lo más probable es que el usuario no haya liberado
la presión de la tecla del primer Aclick@ cuando el programa consulte por el estado de la tecla correspondiente
al segundo Aclick@. Como consecuencia de ello deberemos esperar que el primer Aclick@ define los dos puntos
(iguales) en la pantalla. Una forma de solucionar este problema es que cuando se hace la segunda lectura, se
compare los valores de las coordenadas leídas, con los valores obtenidos en la primera lectura (y que se han
guardado en memoria: cmp CX, COLUMNA1 je LEER2). Si las coordenadas son iguales, se deberá volver
a leer el botón del ratón ya que significa que éste no se ha movido aún.
(**) Para dividir por 8:
a) Una forma simple de dividir por 8, consiste en aplicar la siguiente idea: Se desplaza 3 veces los bits de un
registro hacia la derecha (3 veces, ya que 8 = 2 elevado a 3), poniendo 0 en los lugares que quedan libres a la
izquierda; esta tarea se puede realizar en 80x86 con la instrución SHR Reg, 3 (Shift Right), donde Reg es un
registro de 8 o 16 bits. Vea sus apuntes, Conjunto básico de instrucc..., pág 24, Instrucciones lógicas.
b) DIV Reg8bits,
Divide AX por el contenido del Registro de 8 bits especificado. El
cuociente queda en AL y el resto en AH.
También existe DIV Reg16bits,
(DX:AX) / Reg16bits = cuociente en AX y resto en DX.
1
2.- Dada un área marcada en la pantalla de un computador con video VGA (ver figura adjunta),
definida por los pares ordenados (X1, Y1) y (X2, Y2) dispuesos como variables en la memoria,
proponga un programa que capture ese texto y atributos, en un archivo que se crea en el directorio
c:\captura y de nombre pant0.vid. Por simplicidad, suponga que X1 < X2, e Y1 < Y2. Suponga
estas coordenadas como Words, en variables en
memoria.
Ayuda: Naturalmente, habría varios métodos. Uno
simple puede consistir en transcribir las partes de
VRAM a un Abuffer@, para luego transcribir éste en
el archivo creado. También en este caso puede
trabajar con coordenadas X,Y y calcular el Offset
correspondiente mediante la rutina conocida.
Para calcular la cantidad de words (bytes) puede
usar la instrucción MUL (multiplicar), la que opera
de la siguiente manera: MUL Reg8bits,
multiplica el contenido de AL por el contenido del
Registro de 8 bits especificado. El producto resulta en AX (16 bits). Si el registro especificado es de
16 bits, DX:AX <--- AX*Reg16bits
_____________________________________________________________________________
3.- Proponga un programa que determine si a partir de la posición 02E0H=736 de un archivo
dado, existe la cadena de 16 bytes indicada. Si la cadena existe, la rutina emite un mensaje ASe
ha detectado el virus GUATON.@; en cambio, si esta cadena no existe a partir de la posición
señalada, el mensaje será AEl archivo está libre del virus GUATON.@.
Suponga que el nombre del archivo se ingresó mediante la cola de órdenes, y que esta cola está
transformada en ASCIIZ ( por lo que no necesita incluir estas instrucciones). La rutina termina
cerrando el archivo.
CADENA
db 08h, 63h, 3Ah, 5Ch, 0FFh, 2Eh, 65h, 78h, 605h, 55h, 89h, 0E5h, 31h
db 0C0h, 9Ah, 7Ch
_____________________________________________________________________________
2
4.- Aparece en la pantalla del computador (modo texto 80x25) dos opciones, en la forma
indicada:
1.- Proseguir la tarea.
2.- Terminar la tarea.
La opción 1 está escrita a partir de (25, 10) y hasta (48, 10) y la opción 2 está escrita a partir de
(25, 14) y hasta (48, 14).
Nota: (X, Y) = (Columna, Hilera).
Suponiendo que el ratón ya está activado en pantalla, proponer una rutina que borre la pantalla, para
luego emitir en la misma el mensaje ALa tarea sigue ...@ , o el mensaje ATarea finalizada.@, según
se haga Aclick@ con el botón izquierdo en algún lugar del espacio que ocupa en pantalla la opción 1,
o la opción 2.
Nota: Para transformar coordenadas de ratón 640x200 a coordenadas texto 80x25, debe dividir por 8, lo que
puede hacer mediante instrucción de desplazamiento: shr CX (DX), 3. Desplazar (shift) tres lugares a la
derecha (right) equivale a multiplicar CX (o DX) por 2 elevado a 3.
_____________________________________________________________________________
5.- Proponer un programa que informe sobre el vector de interrupción ascociado con una
determinada interrupción.
El programa se inicia consultado el número de la interrupción. El usuario ingresa el valor y termina
con retorno.
Nota: El ingreso es ASCII, el que deberá transformar en HEX. Para ello identifique si es un número
o letra (mayúscula, minuscula) y transforme en HEX mediante resta (-30H, -37H = 41H - 0AH,
etc..). Luego, mediante rotación haga que el cuarteto menos significativo quede como más
significativo y aplique OR para unir ambos "nibbles".
Mediante la función 35H/21H puede averiguar el vector correspondiente. Este se entrega en HEX,
por lo que deberá transformar a ASCII para emitirlo a pantalla. Para ello, lo más simple (hay otras
formas, identificando y sumado un valor ...), es usar la función XLAT (se acompaña información).
______________________________________________________________________________
6.- La función 36H/21H del DOS informa sobre el espacio que está ocupado y disponible en una
unidad de disco.
Para llamar, AH=36H, DL=Unidad de disco (0=defecto, 1=A, 2=B, 3=C ..., etc.).
Devuelve, en AX=Cantidad de sectores por "cluster" (0FFFFH=-1 si la unidad de disco es no válida).
En BX, el número de "cluster" disponibles o libres. En CX, la cantidad de bytes por sector, y en DX,
la cantidad total de "cluster" en el disco.
Un "cluster" es un conjunto de sectores del disco. Típicamente para un disco removible hay dos
sectores por "cluster", y en el caso de un disco fijo, suelen ser muchos más.
Para calcular el espacio disponible en el disco: DX*AX*CX
3
Para calcular el espacio libre en el disco: AX*BX*CX
(Hacer multiplicaciones a nivel de 32 bits).
Proponer un programa que al ejecutarse indicándosele la unidad de disco (manejo de la cola de
órdenes), informa en pantalla el espacio libre que aún le queda al disco. (Ej.: C:\>libre b: )
Puede confirmar la operación con el comando CHKDSK del DOS.
Para transformar información HEX en DECimal, se acompaña información, al igual que para
transformar DEC en ASCII.
____________________________________________________________________________
7.- La función 57H/21H del DOS permite leer o definir la fecha y la hora asociada con un determinado
archivo. Para llamar: AH=57H
Si AL=00, se lee la fecha y la hora del archivo cuyo "handle" está en BX (archivo previamente abierto o
creado). Retorna en CX la hora y en DX la fecha, según explicación adjunta.
Si AL=01, se define la fecha y la hora del archivo cuyo "handle" está en BX (archivo previamente abierto o
creado). Además en CX se anota la hora y en DX se anota la fecha, según explicación adjunta.
En ambos casos (AL=0 y 01) retorna además en AX el código de error si la bandera de "carry" se puso en 1.
Si AX=01, la función es inválida; si AX=06, el "handle" es inválido.
Interpretación de la hora (en CX):
Más a la izquierda, el bit más significativo. Más a la derecha, el bit menos significativo.
xxxxx... ........
.....xxx xxx.....
........ ...xxxxx
Hora (0 a 23)
Minutos (0 a 59)
Incremento de 2 segundos (0 a 29)
Interpretación de la fecha (en DX):
Más a la izquierda, el bit más significativo, ... id. anterior.
xxxxxxx. ........
Año a partir de 1980
.......x xxx.....
Mes (1 a 12)
........ ...xxxxx
Día (1 a 31)
_____________________________________________________________________________
8.- Proponer un programa que consulte por el nombre de un archivo en disco (0AH/21H). Una vez ingresado
ese nombre, el programa informa sobre la hora y la fecha asignada a este archivo (en la hora evite las décimas
de segundo) o informa si el archivo no se encontró. Luego consulta al usuario si desea cambiar esta asignación.
Si el usuario responde No, el programa termina. Si responde Si, el programa permite el ingreso de una nueva
fecha y de una nueva hora (ofrecer un modelo de ingreso al usuario, similar al ofrecido por los comandos
DATE y/o TIME del DOS). Una vez ingresados estos datos, tanto la hora como la fecha asociadas con el
archivo, cambian. El programa termina.
Para identificar valores, tanto en CX y en DX, realice procesamiento lógico: AND para enmascarar y luego
rotaciones para acomodar. Para realizar conversiones HEX a DEC y a ASCII (y viceversa) estudiar toda la
información adjunta.
________________________________________________________________
4
9.- ( Para trabajar en equipo)
Crear en lenguaje Ensamblador 80x86 un Editor de Textos simple y básico (MINIED.COM). Este
Editor será usado para tareas simples, por lo que sólo incluirá las herramientas básicas para la
edición.
Para su ejecución requiere incluir una cola de órdenes con el nombre del archivo, unidad de disco y paso si
fuera necesario. Si no se incluye esta "cola" el programa puede terminar informando que el usuario debe incluir
esta cola al ejecutar el programa. También pudiera ser que el programa no termine sino que emita un mensaje
a pantalla solicitando el ingreso del nombre del archivo; una vez ingresado (puede usar la función 0Ah del
DOS u otra rutina que reconozca 08H y 0Dh), el programa prosigue. El programa creará el archivo (5BH/21H).
Optativo: Si existe, lo renombra (56H/21H) con nueva extensión (.BK@) y crea con el nuevo nombre.
Es conveniente limpiar a continuación la pantalla, detectando el tipo de controlador de video que usa, de
manera que este Editor sirva en todas las máquinas usuales. Además, la última línea de la pantalla de texto le
servirá para poner un mensaje: .... Para salir y salvar presione F3 ..... ESC para salir sin salvar .... (o algo
similar).
El ingreso del texto se realizará sin eco hacia un "buffer" cuyo inicio es apuntado al final del programa y que
no podrá exceder unos 60 Kbytes (Tamaño máximo del Segmento menos el espacio requerido para los Códigos
del programa y el espacio para la Pila). El efecto de eco sobre la pantalla será realizado por este mismo
programa editor, mediante escritura directa en la Memoria de Video, la que podrá incluir atributos especiales.
Deberá solucionar los problemas derivados del ingreso de caracteres de control 08h=Retroceso y 0Dh=Retorno
de Carro como efecto sobre la escritura de la memoria de Video (tal vez sea esta parte la que más trabajo le
demandará). Lleve en variables de memoria un control de la columna e hilera que está escribiendo en cada
oportunidad. De esta manera será relativamente simple deducir que hacer si se ingresan los caracteres de
control mencionados.
Será necesario también que lleve un control de la cantidad de caracteres ingresados, lo que servirá
posteriormente para Escribir en el Archivo (40H/21H), previo posicionamiento del Puntero del Archivo
(42H/21H).
La escritura y cierre (o borrado) del archivo (3EH/21H) se realizará cuando el usuario presione las teclas
definidas (F3 o Esc, por ejemplo) o cuando con el Ratón haga "click" con el botón izquierdo en la última línea
de la pantalla, al lado derecho o izquierdo (F3, Esc).
Se sugiere simplificar el manejo de errores producidos por las funciones "handle". Si hay "carry" (jc ...)
termina el programa cerrando el archivo (3EH/21H) creado - si alcanzó a crearse - luego borrándolo
(41H/21H), y emitiendo un mensaje único a pantalla que informe al usuario algo así: "Se ha producido un error
relacionado con el archivo, el que pudiera deberse a ruta no encontrada, acceso negado, u otro." (O algo similar
...)
_____________________________________________________________________________
5
10.- (Para trabajar en equipo)
Un archivo textual que se encuentra en el mismo disco del programa, tiene un contenido que
se puede dividir en tres (o más) partes, una a continuación de otra. Cada una de estas partes es un
párrafo o capítulo del texto. Se solicita hacer un programa que permita leer estas partes en la pantalla
de un computador (pantalla HGC o VGA).
Al ejecutarse el programa aparece un menú en alguna posición de pantalla. Las opciones que
ofrece este menú se refieren a cada una de las partes del texto. Una de las letras de cada opción
aparece destacada de alguna forma.
Entonces, teniendo el "ratón" activo, podrá seleccionar alguna de esas opciones. También
podrá seleccionar una opción presionando la tecla destacada, o ALT + tecla de letra destacada si
carece de "ratón". Producida la selección de opción, la pantalla se limpiará, se abrirá el archivo que
se encuentra en disco, se selecciona el párrafo o la parte del texto que se desplegará en pantalla
(42H/21H), se lee ese párrafo (transferencia a RAM) y se muestra en pantalla.
Cada párrafo termina con una indicación " ... presionar cualquier tecla para terminar ... ", lo
que justamente debe ocurrir.
Después del término, la pantalla vuelve a quedar exactamente igual que estaba antes de
activar el menú. De la misma forma, estando el menú en pantalla, y decidiendo el usuario no hacer
selección alguna, mediante la tecla ESC desaparecerá el menú de pantalla volviendo ésta a quedar
tal cual era originalmente. Se sugiere que al comienzo del programa almacene los 4000 bytes
completos de video texto, para transcribirlos al final (condición ESC o condición "... cualquier tecla
... ").
________________________________________________________________
ass_p3.wpd - 24, sbm junio 1999.
LA INSTRUCCION XLAT (traducir, transformar...)
6
XLAT define una posición dentro de una tabla de bytes, para obtener el valor relacionado o
correspondiente con un índice. Se usa el valor AL como índice o desplazamiento dentro de la tabla. El
registro BX es usado para apuntar el comienzo de la tabla. La instrucción XLAT devuelve el valor
correspondiente o relacionado en el mismo registro AL. La longitud máxima de la tabla es de 256 bytes y
debe ser de tipo byte (el índice en AL es un byte). El primer byte de la tabla tiene "offset" o
desplazamiento cero.
La tabla de valores relacionados con el índice (contenido de AL en esta caso) se conoce como tabla de
inspección o consulta ("look up table"). La idea consiste en realizar la transformación de un valor en
otro, mediante la consulta del valor relacionado en una tabla, en lugar de usar algún procesamiento
matemático.
Ejemplo:
La transformación HEX/ASCII se realiza mediante procesamiento aritmético lógico (si es
00H...09H se suma 30H, si es 0AH....0FH se suma 37H o bien 57H). También es posible realizarla
mediante transformación o traducción directa. Esto último se ilustra a continuación.
Supongamos el dato HEX (00H...0FH) en el registro DL. Entonces,
TRADUCE:
HEX_ASCII
mov BX, offset HEX_ASCII
;inicio de la tabla
mov AL, DL
;dato en DL, por ejemplo
xlat
;o simplemente XLAT
.....
;devuelve dato ASCII correspondiente, en AL.
.....
db 30H, 31H, 32H, 33H, 34H, 35H, 36H, 37H, 38H, 39H
db 41H, 42H, 43H, 44H, 45H, 46H
Notará en el ejemplo anterior que si, por ejemplo, AL es igual a 0AH, la traducción resultará en el valor
41H. El proceso anterior es equivalente con la instrucción
MOV AL, HEX_ASCII[BX]
Como el valor de AL inicial (antes de ejecutar XLAT) define el "offset" dentro de la tabla, el valor 00 se
transforma en el primer byte de ésta, el valor 01H en el segundo valor de ésta, etc.. En consecuencia, este
proceso sólo resulta útil cuando los valores en AL (índice) varían en forma contínua desde 00 hasta un
máximo de 255 (00H...FFH).
No todas las traducciones o transformaciones se pueden realizar cómodamente con la instrucción XLAT.
Por ejemplo, no resulta apropiado traducir ASCII/HEX mediante el uso de este recurso, ya que los valores
ASCII correspondientes con los dígitos HEX no son contínuos. Además de no iniciarse en 00 (lo que se
podría solucionar fácilmente restando 30H), existen los "huecos" o discontinuidades 3AH, 3BH....40H. En
este caso la transformación ASCII/HEX se puede realizar simplemente mediante procesamiento aritmético
lógico: Si es 30H...39H se resta 30H, si es 41H....46H se resta 37H, si es 61H....66H se resta 57H.
sbm/1994. xlat.w51-14
7
CONVERSION HEX A DEC.
Rutina que transforma un dato (entre 0 y 9999) en 4 bytes ASCII, cada uno correspondiente a una cifra del
dato. Estos se muestran en pantalla.
Idea de base:
6789/10 = 678
678/10 = 67
67/10 = 6
6/10 = 0
resto 9
resto 8
resto 7
resto 6
(note los restos ...)
La instrucción DIV REG16 divide AX por REG16 (16 bits) dejando el cuociente el AX y el resto en DX.
HEX_DEC:
RESTO:
mov ax, DATO
mov si, 0AH
mov cx, 04
xor dx, dx
div si
push dx
loop RESTO
DOASCII:
;en AX el dato entre 0 y 9999
;para dividir por 10
;hacer un "loop" 4 veces, 4 cifras
;DX=0
;AX/10, cuociente en AX y resto en DX
;guardar el resto en la pila
;volver a dividir y salvar el resto
mov bx, offset DATMEM
mov cx, 04
OTRODATO: pop ax
add ax, 30H
mov [bx], al
inc bx
loop OTRODATO
PANTALLA:
LEERDAT:
MOSTRAR:
mov ah, 02
mov cx, 04
mov dl, [bx]-4
cmp dl, 30H
jnz MOSTRAR
sub dl, 30H
inc bx
int 21H
loop LEERDAT
;definir un "buffer"
;4 cifras, "loop"
;recuperar datos pila
;transformar en ASCII
;guardar en "buffer"
;sgte. posición ...
;sgte. dato ...
;mostrar en pantalla usando 02/21H
;4 cifras
;partiendo del último dato ...
;si es 0, no mostrar en pantalla
;otro valor, mostrar ...
;hacer de 30H un dato nulo
;siguiente dato
;función 02/21H
;siguiente dato ...
FINAL:int 20H
DATMEM
db 4 dup (?)
;reserva de memoria
;sbm/
;HEX_DEC.w51-14
8
Descargar