Make your own free website on Tripod.com

Interrupciones


Introducción

IBM tomó una decisión respecto a la arquitectura de sus computadoras personales destinada a marcar un cambio notable en la historia de la tecnología. Adoptó una arquitectura abierta, esto es, utilizó componentes que estaban en el mercado en lugar de fabricar chips propietarios. Al tomar esta resolución, Intel pasó a ser la opción más clara como proveedor de procesadores y periféricos: por aquél entonces acababa de salir al mercado la línea de 16 bits 8086 y existían muchos periféricos de 8 bits de su predecesor, el 8085, tales como el controlador de interrupciones 8259, el PPI 8255, DMA 8237,  la UART 8251, el timer 8253. En los procesadores Intel de la línea X86, hay dos tipos de interrupciones: por hardware y por software. En las primeras, una señal llega a uno de los terminales de un controlador de interrupciones 8259 y éste se lo comunica al procesador mediante una señal LOW en su pin INT. El procesador interroga al 8259 cuál es la fuente de la interrupción (hay 8 posibles en un 8259) y este le muestra en el bus de datos un vector que la identifica. Por instrucciones de programa, se puede instruir al 8086 para que ignore la señal en el pin INT, por lo que estas interrupciones se denominan "enmascarables". Hay un pin adicional llamado NMI, que se comporta como una interrupción, pero imposible de bloquear (Non-Maskable-Interrupt).

Tipos de interrupciones

Interrupciones internas de hardware

Las interrupciones internas son generadas por ciertos eventos que surgen durante la ejecución de un programa. Este tipo de interrupciones son manejadas en su totalidad por el hardware y no es posible modificarlas. Un ejemplo claro de este tipo de interrupciones es la que actualiza el contador del reloj interno de la computadora, el hardware hace el llamado a esta interrupción varias veces durante un segundo para mantener la hora actualizada. Aunque no podemos manejar directamente esta interrupción (no podemos controlar por software las actualizaciones del reloj), es posible utilizar sus efectos en la computadora para nuestro beneficio, por ejemplo para crear un "reloj virtual" actualizado continuamente gracias al contador del reloj interno. Únicamente debemos escribir un programa que lea el valor actual del contador y lo traduzca a un formato entendible para el usuario.

Interrupciones externas de hardware

Las interrupciones externas las generan los dispositivos perifericos, como pueden ser: teclado, impresoras, tarjetas de comunicaciones, etc. También son generadas por los coprocesadores. No es posible desactivar a las interrupciones externas. Estas interrupciones no son enviadas directamente a la UCP, sino que se mandan a un circuito integrado cuya función es exclusivamente manejar este tipo de interrupciones. El circuito, llamado PIC 8259A, si es controlado por la UCP utilizando para tal control una serie de vias de comunicación llamadas puertos.

Interrupciones de software

Las interrupciones por software se comportan de igual manera que las de hardware pero en lugar de ser ejecutadas como consecuencia de una señal física, lo hacen con una instrucción. Las interrupciones de software pueden ser activadas directamente por el ensamblador invocando al número de interrupción deseada con la instrucción INT. El uso de las interrupciones nos ayuda en la creación de programas, utilizándolas nuestros programas son más cortos, es más fácil entenderlos y usualmente tienen un mejor desempeño debido en gran parte a su menor tamaño. Este tipo de interrupciones podemos separarlas en dos categorías: las interrupciones del sistema operativo DOS y las interrupciones del BIOS. La diferencia entre ambas es que las interrupciones del sistema operativo son más fáciles de usar pero también son más lentas ya que estas interrupciones hacen uso del BIOS para lograr su cometido, en cambio las interrupciones del BIOS son mucho más rápidas pero tienen la desventaja que, como son parte del hardware son muy específicas y pueden variar dependiendo incluso de la marca del fabricante del circuito. La elección del tipo de interrupción a utilizar dependerá únicamente de las características que le quiera dar a su programa: velocidad (utilizando las del BIOS) o portabilidad (utilizando las del DOS).

Hay en total 256 interrupciones, de la 0 a la 7 (excepto la 5) son generadas directamente por el procesador. Las 8 a 0Fh son interrupciones por hardware primitivas de las PC. Desde la AT en adelante, se incorporó un segundo controlador de interrupciones que funciona en cascada con el primero a través de la interrupción 2 (de ahí que en la tabla siguiente se la denomine múltiplex). Las 8 interrupciones por hardware adicionales de las AT se ubican a partir del vector 70h.

Decimal

Hexa

Generada

Descripción

0

0

CPU

División por cero

1

1

CPU

Single-step

2

2

CPU

NMI

3

3

CPU

Breakpoint

4

4

CPU

Desbordamiento Aritmético

5

5

BIOS

Imprimir Pantalla

6

6

CPU

Código de operación inválido

7

7

CPU

Coprocesador no disponible

8

8

HARD

Temporizador del sistema (18,2 ticks por seg)

9

9

HARD

Teclado

10

0A

HARD

Múltiplex

11

0B

HARD

IRQ3 (normalmente COM2)

12

0C

HARD

IRQ4 (normalmente COM1)

13

0D

HARD

IRQ5

14

0E

HARD

IRQ6

15

0F

HARD

IRQ7 (normalmente LPT1)

112

70

HARD

IRQ8 (reloj de tiempo real)

113

71

HARD

IRQ9

114

72

HARD

IRQ10

115

73

HARD

IRQ11

116

74

HARD

IRQ12

117

75

HARD

IRQ13 (normalmente coprocesador matemático)

118

76

HARD

IRQ14 (normalmente Disco Duro)

119

77

HARD

IRQ15

En cuanto a las interrupciones por software, están divididas entre las llamadas por el BIOS (desde la 10h a la 1Fh) y las llamadas por el DOS (desde la 20h hasta la 3Fh). Esto es sólo la versión oficial, ya que en realidad las interrupciones entre BIOS y DOS se extienden hasta la 7Fh.

Cómo funciona una interrupción

A partir del offset 0 del segmento 0 hay una tabla de 256 vectores de interrupción, cada uno de 4 bytes de largo (lo que significa que la tabla tiene una longitud de 1KB). Cada vector está compuesto por dos partes: offset (almacenado en la dirección más baja) y segmento (almacenado en la dirección más alta). Cuando se llama a una interrupción (no importa si es por hardware o por software), el procesador ejecuta las siguientes operaciones:

1.      PUSHF  (guarda las banderas en el stack)

2.       CTF/DI (borra la bandera de Trap y deshabilita interrupciones)

3.      CALL FAR [4 * INT#]  (salta a nueva CS:IP, almacenando dirección de retorno en stack)

La expresión 4 * INT# es la forma de calcular la dirección de inicio del vector de interrupción a utilizar en el salto. Por ejemplo, el vector de la INT21h estará en la dirección 84h  Al efectuarse el salto, la palabra almacenada en la dirección más baja del vector sustituye al contenido del registro IP (que previamente fue salvado en el stack) y la palabra almacenada en la dirección más alta sustituye al contenido del registro CS (también salvado en el stack). Por ejemplo:

La instrucción INT 21h es la usada para efectuar llamadas a las funciones del DOS. Supongamos que en la posición de memoria 0000:0084 está almacenada la palabra 1A40h y en la dirección 0000:0086 está almacenada la palabra 208Ch. La próxima instrucción que se ejecute es la que está en la posición 20C8:1A40 (nuevo CS:IP).

El final de una rutina de interrupción debe terminarse con la instrucción IRET, que recupera del stack los valores de CS, IP y Flags.

Notemos que un llamado a interrupción implica el cambio de estado automático de la bandera de habilitación de interrupciones. En pocas palabras, esto significa que al producirse una interrupción, esta bandera inhabilita futuras interrupciones. Como la instrucción IRET restablece el registro de flags al estado anterior que tenia antes de producirse la interrupción, las próximas interrupciones se habilitan en el mismo momento en que se produce el retorno desde la rutina de servicio.

 Paso de parámetros desde el programa a la ISR

Cuando las interrupciones son llamadas por software mediante la instrucción INT xx, por lo general se le deben pasar parámetros a la rutina de servicio de interrupción (ISR). Estos parámetros definen la tarea que debe cumplir la ISR y son pasados en los registros del procesador, lo que es una opción muy veloz.

Un ejemplo casi extremo, en donde muchos de los registros del 8086 son utilizados son algunos servicios cumplidos por la INT 13h (disco). Para tomar sólo un caso, en una operación de escritura de un sector, los parámetros se pasan de la siguiente manera:

Registro

Asignación

AH

03 (servicio de escritura de sectores)

AL

cantidad de sectores a escribir

CH

8 bits más bajos del número de cilindro

CL(bits 0-5)

número de sector

CL(bits 6 y 7)

2 bits más altos del número de cilindro

DH

número de cabeza

DL

número de unidad de disco (hard: mayor a 80h)

BX

offset del buffer de datos

ES

segmento del buffer de datos

Si bien no está escrito en ningún lado, las interrupciones utilizan el registro AH para identificar el tipo de operación que deben ejecutar. Cuando una interrupción devuelve códigos de error siempre vienen en el registro AL, AX y/o en la bandera de Carry.

Interrupción 21H

Propósito: Llamar a diversas funciones del DOS.

Sintaxis:

Int 21H

Nota: Cuando trabajamos en MASM es necesario especificar que el valor que estamos utilizando es hexadecimal.

Esta interrupción tiene varias funciones, para accesar a cada una de ellas es necesario que el el registro AH se encuentre el número de función que se requiera al momento de llamar a la interrupción.

Función

Descripción

00h

Terminar un programa

01h

Entrada de caracteres con salida

02h

Salida de un caracter

03h

Recepción de un caracter por el puerto serial

04h

Envío de un caracter por el puerto serial

05h

Salida por puerto paralelo

06h

Entrada/salida de caracteres directa

07h

Entrada/salida de caracteres directa

08h

Entrada de caracteres sin salida

09h

Salida de un string de caracteres

0Ah

Entrada de un string de caracteres

0Bh

Leer estado de una entrada

0Ch

Borra buffer de entrada y llama a entrada de caracteres

0Dh

Reset de los drivers de bloques

0Eh

Selección de unidad actual

0Fh

Abrir archivo usando FCBs (File Control Blocks)

10h

Cerrar archivo (FCBs)

11h

Busca primera entrada de directorio (FCBs)

12h

Busca siguiente entrada de directorio (FCBs)

13h

Borrar archivo(s) (FCBs)

14h

Lectura secuencial (FCBs)

15h

Escritura secuencial (FCBs)

16h

Crear o vaciar un archivo (FCBs)

17h

Renombrar archivos (FCBs)

18h

Obsoleta

19h

Obtener denominación de dispositivo, unidad actual

1Ah

Fijar dirección para DTA (Disk Transfer Area)

1Bh

Obtener información sobre unidad actual

1Ch

Obtener información sobre una unidad cualquiera

1Dh/1Eh

Obsoletos

1Fh

Fijar puntero a DPB (Drive Parameter Block) a la unidad actual

20h

Obsoleta

21h

Lectura random (FCB)

22h

Escritura random (FCB)

23h

Leer tamaño de archivo (FCB)

24h

Establecer número de registro (FCB)

25h

Establecer vector de interrupción

26h

Crear nuevo PSP (Program Segment Prefix)

27h

Lectura random de varios registros (FCB)

28h

Escritura random de varios registros (FCB)

29h

Transferir nombre de archivo al FCB

2Ah

Obtener fecha

2Bh

Establecer fecha

2Ch

Obtener hora

2Dh

Establecer hora

2Eh

Fijar bandera de Verify

2Fh

Obtener DTA

30h

Obtener número de versión del DOS

31h

Terminar programa pero dejarlo residente en memoria

32h

Obtener puntero a DPB de una unidad específica

33h

Leer/escribir bandera de break

34h

Obtener dirección de bandera INDOS

35h

Leer vector de interrupción

36h

Obtener espacio de disco disponible

37h

Obtener/fijar signo p/separador de línea de comandos

38h

Obtener/fijar formatos específicos de un país

39h

Crear subdirectorio

3Ah

Borrar subdirectorio

3Bh

Fijar directorio actual

3Ch

Crear o vaciar archivo (handle)

3Dh

Abrir archivo (handle)

3Eh

Cerrar archivo (handle)

3Fh

Leer desde archivo (handle)

40h

Escribir en archivo (handle)

41h

Borrar archivo (handle)

42h

Mover puntero de archivo (handle)

43h

Obtener/fijar atributo de archivo

44h

Funciones IOCTL (control de I/O)

45h

Duplicar handle

46h

Duplicación forzosa de handles

47h

Obtener directorio actual

48h

Reservar memoria RAM

49h

Liberar memoria RAM

4Ah

Modificar tamaño de memoria reservada

4Bh

EXEC: ejecutar o cargar programas

4Ch

Terminar programa con valor de salida

4Dh

Obtener valor de salida de un programa

4Eh

Buscar primera entrada en el directorio (handle)

4Fh

Buscar siguiente entrada en el directorio (handle)

50h

Establecer PSP activo

51h

Obtener PSP activo

52h

Obtener puntero al DOS-info-block

53h

Traducir Bios Parameter Block a Drive Parameter Block

54h

Leer bandera Verify

55h

Crear PSP nuevo

56h

Renombrar o mover archivo

57h

Obtener/fijar fecha y hora de modificación de archivo

58h

Leer/fijar estrategia de alocación de memoria

59h

Obtener informaciones de error ampliadas

5Ah

Crear archivo temporal (handles)

5Bh

Crear archivo nuevo (handles)

5Ch

Proteger parte de un archivo contra accesos

5Dh

Funciones de Share.exe

5Eh

Obtener nombres de dispositivos de red

5Fh

Obtener/fijar/borrar entrada de la lista de red

60h

Ampliar nombre de archivo

61h

No usada

62h

Obtener dirección del PSP

63h/64h

No usadas

65h

Obtener información ampliada de pais específico

66h

Obtener/fijar página de códigos actual

67h

Determinar el número de handles disponibles

68h

Vaciar buffer de archivos

69/6A/6B

No usadas

6Ch

Función Open ampliada

Función 02H

Uso:

Despliega un caracter a la pantalla.

Registros de llamada:

AH = 02H

DL = Valor del caracter a desplegar.

Ninguno

Esta función nos despliega el caracter cuyo codigo hexagesimal corresponde al valor almacenado en el registro DL, no se modifica ningún registro al utilizar este comando.

Es recomendado el uso de la función 40H de la misma interrupción en lugar de esta función.

Función 09H

Despliega una cadena de carateres en la pantalla.

AH = 09H

DS:DX = Dirección de inicio de una cadena de caracteres

Ninguno.

Esta función despliega los caracteres, uno a uno, desde la dirección indicada en el registro DS:DX hasta encontrar un caracter $, que es interpretado como el final de la cadena.

Se recomienda utilizar la función 40H en lugar de esta función.

Función 40H

Escribir a un dispositivo o a un archivo.

AH = 40H

BX = Vía de comunicación

CX = Cantidad de bytes a escribir

DS:DX = Dirección del inicio de los datos a escribir

CF = 0 si no hubo error

AX = Número de bytes escritos

CF = 1 si hubo error

AX = Código de error

El uso de esta función para desplegar información en pantalla se realiza dandole al registro BX el valor de 1 que es el valor preasignado al video por el sistema operativo MS-DOS.

Función 01H

Leer un caracter del teclado y desplegarlo.

AH = 01H

AL = Caracter leído

Con esta función es muy sencillo leer un caracter del teclado, el código hexadecimal del caracter leído se guarda en el registro AL. En caso de que sea un caracter extendido el registro AL contendra el valor de 0 y será necesario llamar de nuevo a la función para obtener el código de este caracter.

Función 0AH

Leer caracteres del teclado y almacenarlos en un buffer.

AH = 0AH

DS:DX = Dirección del área de almacenamiento

BYTE 0 = Cantidad de bytes en el área

BYTE 1 = Cantidad de bytes leídos

desde BYTE 2 hasta BYTE 0 + 2 = caracteres leídos

Ninguno

Los caracteres son leídos y almacenados en un espacio predefinido de memoria. La estructura de este espacio le indica que en el primer byte del mismo se indican cuantos caracteres serán leídos. En el segundo byte se almacena el número de caracteres que ya se leyeron, y del tercer byte en adelante se escriben los caracteres leídos.

Cuando se han almacenado todos los caracteres indicados menos uno la bocina suena y cualquier caracter adicional es ignorado. Para terminar la captura de la cadena es necesario darle [ENTER].

Función 3FH

Leer información de un dispositivo o archivo.

AH = 3FH

BX = Número asignado al dispositivo

CX = Número de bytes a procesar

DS:DX = Dirección del área de almacenamiento

CF = 0 si no hay error y AX = número de bytes leidos.

CF = 1 si hay error y AX contendra el código del error.

Función 0FH

Abrir archivo FCB

AH = 0FH

DS:DX = Apuntador a un FCB

AL = 00H si no hubo problema, de lo contrario regresa 0FFH

Función 14H

Leer secuencialmente un archivo FCB.

AH = 14H

DS:DX = Apuntador a un FCB ya abierto.

AL = 0 si no hubo errores, de lo contrario se regresara el código correspondiente de error: 1 error al final del archivo, 2 error en la estructura del FCB y 3 error de lectura parcial.

Esta función lo que hace es que lee el siguiente bloque de información a partir de la dirección dada por DS:DX, y actualiza este registro.

Función 15H

Escribir secuencialmente a un archivo FCB

AH = 15H

DS:DX = Apuntador a un FCB ya abierto

AL = 00H si no hubo errores, de lo contrario contendra el código del error: 1 disco lleno o archivo de solo lectura, 2 error en la formación o especificación del FCB.

La función 15H después de escribir el registro al bloque actual actualiza el FCB.

Función 16H

Crear un archivo FCB.

AH = 16H

DS:DX = Apuntador a un FCB ya abierto.

AL = 00H si no hubo errores, de lo contrario contendra el valor 0FFH

Se basa en la información proveida en un FCB para crear un archivo en el disco.

Función 21H

Leer en forma aleatoria un archivo FCB.

AH = 21H

DS:DX = Apuntador a un FCB ya abierto.

A = 00H si no hubo error, de lo contrario AH contendra el código del error: 1 si es fin de archivo, 2 si existe error de especificación de FCB y 3 si se leyó un registro parcial o el apuntador del archivo se encuentra al final del mismo.

Esta función lee el registro especificado por los campos del bloque actual y registro actual de un FCB abierto y coloca la información en el DTA (área de transferencia de disco o Disk Transfer Area).

Función 22H

Escribir en forma aleatoria en un archivo FCB.

AH = 22H

DS:DX = Apuntador a un FCB abierto.

AL = 00H si no hubo error, de lo contrario contendrá el código del error: 1 si el disco está lleno o es archivo de solo lectura y 2 si hay error en la especificación de FCB.

Escribe el registro especificado por los campos del bloque actual y registro actual de un FCB abierto. Escribe dicha información a partir del contenido del DTA (área de transferencia de disco).

Función 3CH

Crear un archivo si no existe o dejarlo en longitud 0 si existe. (Handle)

AH = 3CH

CH = Atributo de archivo

DS:DX = Apuntador a una especificaión ASCIIZ

CF = 0 y AX el número asignado al handle si no hay error, en caso de haberlo CF será 1 y AX contendra el código de error: 3 ruta no encontrada, 4 no hay handles disponibles para asignar y 5 acceso negado.

Esta función sustituye a la 16H. El nombre del archivo es especificado en una cadena ASCIIZ, la cual tiene como característica la de ser una cadena de bytes convencional terminada con un caracter 0.

El archivo creado contendra los atributos definidos en el registro CX en la siguiente forma:

 

Valor Atributos

00H Normal

02H Escondido

04H Sistema

06H Escondido y de sistema

El archivo se crea con los permisos de lectura y escritura. No es posible crear directorios utilizando esta función.

Función 3DH

Abre un archivo y regrese un handle

AH = 3DH

AL = modo de acceso

DS:DX = Apuntador a una especificación ASCIIZ

CF = 0 y AX = número de handle si no hay errores, de lo contrario CF = 1 y AX = código de error: 01H si no es válida la función, 02H si no se encontró el archivo, 03H si no se encontr´o la ruta, 04H si no hay handles disponibles, 05H en caso de acceso negado, y 0CH si el código de acceso no es válido.

El handle regresado es de 16 bits.

El código de acceso se especifica en la siguiente forma:

 

BITS

7 6 5 4 3 2 1

. . . . 0 0 0 Solo lectura

. . . . 0 0 1 Solo escritura

. . . . 0 1 0 Lectura/Escritura

. . . X . . . RESERVADO

Función 3EH

Cerrar archivo (Handle).

AH = 3EH

BX = Handle asignado

CF = 0 si no hubo errores, en caso contrario CF será 1 y AX contendrá el código de error: 06H si el handle es inválido.

Esta función actualiza el archivo y libera o deja disponible el handle que estaba utilizando.

Función 3FH

Leer de un archivo abierto una cantdad definida de bytes y los almacena en un buffer específico.

AH = 3FH

BX = Handle asignado

CX = Cantidad de bytes a leer

DS:DX = Apuntador a un área de trabajo.

CF = 0 y AX = número de bytes leidos si no hubo error, en caso contrario CF = 1 y AX = código de error: 05H si acceso negado y 06H si no es válido el handle.

Función 40H

Escribe a un archivo ya abierto una cierta cantidad de bytes a partir del buffer designado.

AH = 40H

BX = Handle asignado

CX = Cantidad de bytes a escribir.

DS:DX = Apuntador al buffer de datos.

CF = 0 y AX = número de bytes escritos si no hay errores, en caso de existir CF = 1 y AX = código del error: 05H si el acceso es negado y 06H si el handle es inválido.

Función 42H

Mover apuntador al archivo (Handle)

AH = 42H

AL = método utilizado

BX = Handle asignado

CX = La parte más significativa del offset

DX = La parte menos significativa del offset

CF = 0 y DX:AX = la nueva posición del apuntador. En caso de error CF será 1 y AX = código de error: 01H si la función no es válida y 06H si el handle no es válido.

El método utilizado se configura como sigue:

 

Valor de AL Método

00H A partir del principio del archivo

01H A partir de la posición actual

02H A partir del final del archivo

Interrupción 10H

Propósito: Llamar a diversas funciones de video del BIOS.

Sintaxis:

Int 10H

Esta interrupción tiene diversas funciones, todas ellas nos sirven para controlar la entrada y salida de video, la forma de acceso a cada una de las opciones es por medio del registro AH.

En este tutorial unicamente veremos algunas de las funciones de esta interrupción.

 

Función 02H

Posiciona el cursor en la pantalla dentro de las coordenadas válidas de texto.

AH = 02H

BH = Página de video en la que se posicionará el cursor.

DH = Fila

DL = Columna

Ninguno.

Las posiciones de localización del cursor son definidas por coordenadas iniciando en 0,0, que corresponde a la esquina superior izquierda hasta 79,24 correspondientes a la esquina inferior derecha. Tenemos entonces que los valores que pueden tomar los registros DH y DL en modo de texto de 80 x 25 son de 0 hasta 24 y de 0 hasta 79 respectivamente.

Función 09H

Desplegar un caracter un determinado número de veces con un atributo definido empezando en la posición actual del cursor.

AH = 09H

AL = Caracter a desplegar

BH = Página de video en donde se desplegará

BL = Atributo a usar

Número de repeticiones.

Ninguno

Esta función despliega un caracter el número de veces especificado en CX pero sin cambiar la posición del cursor en la pantalla.

Función 0AH

Desplegar un caracter en la posición actual del cursor.

AH = 0AH

AL = Caracter a desplegar

BH = Página en donde desplegar

BL = Color a usar (sólo en gráficos).

CX = Número de repeticiones

Ninguno.

La única diferencia entre esta función y la anterior es que ésta no permite modificar los atributos, simplemente usa los atributos actuales.

Tampoco se altera la posición del cursor con esta función.

Función 0EH

Deplegar un caracter en la pantalla actualizando la posición del cursor.

AH = 0EH

AL = Caracter a desplegar

BH = Página donde se desplegara el caracter

BL = Color a usar (solo en gráficos)

Ninguno

Interrupción 16H

Propósito: Manejar la entrada/salida del teclado.

Sintaxis:

Int 16H

Veremos dos opciones de la interrupción 16H, estas opciones, al igual que las de otras interrupciones, son llamadas utilizando el registro AH.

 

Función 00H

Leer un caracter del teclado.

AH = 00H

AH = código de barrido (scan code) del teclado

AL = Valor ASCII del caracter.

Cuando se utiliza esta interrupción se detiene la ejecución del programa hasta que se introduzca un caracter desde el teclado, si la tecla presionada es un caracter ASCII su valor será guardado en el registro AH, de lo contrario el código de barrido será guardado en AL y AH contendrá el valor 00H.

El código de barrido fué creado para manejar las teclas que no tienen una representación ASCII como [ALT], [CONTROL], las teclas de función, etc.

Función 01H

Leer estado del teclado.

AH = 01H

Si la bandera de cero, ZF, está apagada significa que hay información en el buffer, si se encuentra prendida es que no hay teclas pendientes.

En caso de existir información el registro AH contendrá el código de la tecla guardada en el buffer.

Interrupción 17H

Propósito: Manejar la entrada/salida de la impresora.

Sintaxis:

Int 17H

Esta interrupción es utilizada para escribir caracteres a la impresora, inicializarla y leer su estado.

 

Función 00H

Escribir un caracter a la impresora.

AH = 00H

AL = Caracter a imprimir

DX = Puerto a utilizar

AH = Estado de la impresora.

El puerto a utilizar, definido en DX, se especifica así: LPT1 = 0, LPT2 = 1, LPT3 = 2 ...

El estado de la impresora se codifica bit por bit como sigue:

 

BIT 1/0 SIGNIFICADO

----------------------------------------

0 1 Se agotó el tiempo de espera

1 -

2 -

3 1 Error de entrada/salida

4 1 Impresora seleccionada

5 1 Papel agotado

6 1 Reconocimiento de comunicación

7 1 La impresora se encuentra libre

Los bits 1 y 2 no son relevantes.

La mayoria de los BIOS unicamente soportan 3 puertos paralelos aunque existen algunos que soportan 4.

Función 01H

Inicializar un puerto de impresión.

AH = 01H

DX = Puerto a utilizar

AH = Status de la impresora

El puerto a utilizar, definido en DX, se especifica así: LPT1 = 0, LPT2 = 1, etc.

El estado de la impresora se codifica bit por bit como sigue:

 

BIT 1/0 SIGNIFICADO

----------------------------------------

0 1 Se agotó el tiempo de espera

1 -

2 -

3 1 Error de entrada/salida

4 1 Impresora seleccionada

5 1 Papel agotado

6 1 Reconocimiento de comunicación

7 1 La impresora se encuentra libre

Los bits 1 y 2 no son relevantes.

La mayoria de los BIOS unicamente soportan 3 puertos paralelos aunque existen algunos que soportan 4.

Función 02H

Obtener el estado de la impresora.

AH = 01H

DX = Puerto a utilizar

AH = Status de la impresora.

El puerto a utilizar, definido en DX, se especifica así: LPT1 = 0, LPT2 = 1, etc.

El estado de la impresora se codifica bit por bit como sigue:

 

BIT 1/0 SIGNIFICADO

----------------------------------------

0 1 Se agotó el tiempo de espera

1 -

2 -

3 1 Error de entrada/salida

4 1 Impresora seleccionada

5 1 Papel agotado

6 1 Reconocimiento de comunicación

7 1 La impresora se encuentra libre

Los bits 1 y 2 no son relevantes.

La mayoria de los BIOS unicamente soportan 3 puertos paralelos aunque existen algunos que soportan 4.

6. Intercepción de interrupciones (hooks)

Un programa puede necesitar "enganchar" una interrupción. Supongamos que hemos creado un virus que debe autodestruir su copia en memoria cuando el comando a ejecutar es "scan.exe". Evidentemente debemos interceptar la interrupción 21h, función 4Bh/00 (cargar un programa y ejecutarlo), de tal manera que "nuestra" función verifique si el programa a cargar se llama scan.exe y en tal caso, borre lo que haya que borrar.

Esta tarea, se logra en haciendo un programa residente (que puede ser parte del mismo código del virus) para que

1.      Cuando se produzca una llamada a la INT21h-4Bh, no se ejecute el código normal del DOS sino nuestro código

2.      En él chequearemos si la función es una 4Bh-00, y en caso afirmativo verificamos si el programa a corres se llama scan.exe. Si todo esto es verdadero, sobrescribiremos las partes sensibles a la detección del virus y lo descargaremos de la memoria.

3.      Finalmente saltamos a la verdadera INT21h función 4Bh

Para lograr esto, es necesario contar con un loader que cargue en memoria nuestro programa. Este loader debe:

1.      Reservar un espacio de memoria adecuado al tamaño del código que quedará residente.

2.      Averiguar (mediante INT21h-35h) cual es el vector de interrupción de la INT21h. Supongamos que sea 0102:2C40h

3.      Poner este vector como dirección de retorno del código residente (por lo general cargándolo en una dirección conocida en donde tiene que estar este valor)

4.      Cambiar el vector 4Bh origina por la dirección de inicio de nuestro código residente (digamos 7E00:0000)

Lo que sucederá cuando la PC infectada con nuestro virus intente ejecutar un scan.exe es lo siguiente:

1.      Dentro del Command.com, se generará un llamado a la INT21-4Bh-00 con scan.exe como parámetro.

2.      El procesador buscará el vector para el servicio a la interrupción 21h en la dirección 0000:0084h

3.      En ese lugar estará la dirección de inicio de nuestro residente, o sea 7E00:0000, y en ese lugar se inicia el procesamiento de la interrupción.

4.      Al ver que la llamada es para ejecutar un programa scan.exe nuestro residente vuelve a poner el vector de INT21h en el valor que le dio el DOS y luego se autodestruye (primero traslada a la parte más baja de la memoria la función de borrado). Como último acto, hace un salto JMP FAR 0102:2C40

5.      Esto último hará que se ejecute scan.exe como si nada hubiese sucedido.

Frecuentemente los virus utilizan interrupciones en desuso para sus fines (por ejemplo para saber si están activos en memoria).

El tema de las interrupciones es tan inmenso que lo que acabamos de ver no es sino un pequeño pantallazo. Quedan cuestiones muy delicadas como la bandera INDOS y las formas de evitar la reentrada. Una descripción muy completa de cada interrupción, que incluye los registros usados para el paso de parámetros, está en el archivo intdos.zip, por Ralph Brown (en inglés) que pueden bajarse de sudden discharge o asmcoder , dos sitios que les recomiendo si se buscan tutoriales o archivos.

Función BIOS para manejo de strings

El BIOS interactúa principalmente de a un caracter por vez con el teclado, pantalla y puerto serial, por lo que a estos se los conoce como dispositivos de caracteres, en contraposición con el drive de diskettes o el disco duro, que son dispositivos de bloques.  Aunque menos frecuente que las funciones de manejo de strings del DOS, la función 13h de la INT10h tiene la ventaja que no depende del sistema operativo. Su función es visualizar en la pantalla una cadena de caracteres que deben estar almacenados en un buffer (en memoria).

El paso de parámetros se realiza mediante los siguientes registros:

Registro

Parámetro

AH

13 h - define la operación

AL

Modo de salida:

0

Atributo en BL, mantiene la posición del cursor

1

Atributo en BL, actualiza la posición del cursor

2

Atributo en buffer, mantiene posición del cursor

3

Atributo en buffer, actualiza posición del cursor

 

BL

Atributo de caracteres (solo modos 0 y 1)

CX

Cantidad de caracteres a visualizar

DH

Línea de la pantalla

DL

Columna de la pantalla

BH

Página de pantalla

ES:BX

Puntero al buffer de memoria

 Los modos que actualizan la posición del cursor se usan cuando se quieren escribir varios strings uno a continuación del otro. En cambio los modos que la mantienen, se utilizan para escribir mensajes siempre en el mismo lugar de la pantalla.

En los modos 0 y 1 todos los caracteres tienen el atributo especificado en BL, mientras que en los modos 2 y 3 en el buffer, seguido a cada caracter esta su byte de atributo, lo que permite que cada caracter tenga un atributo distinto. La cadena en memoria tiene una longitud igual al doble de los caracteres a visualizar. El valor de CX debe ser no obstante igual a la cantidad de caracteres (la mitad del tamaño del buffer). El byte de atributos tiene la siguiente estructura:

Bit #

Función

7

Intermitencia (1=intermitente, 0=fijo)

6,5,4

Color de fondo (0=negro, 7=blanco)

3,2,1,0

Color del caracter (0=negro, 0Fh=blanco) 

 

Funciones DOS de manejo de strings

Entrada de strings de caracteres: INT21h - función 0Ah

Se leen caracteres desde la entrada standard (normalmente teclado) y se transfieren a un búffer en memoria. La operación termina cuando se lee el caracter ASCII 0Dh (CR o retorno de carro), que corresponde a la tecla RETURN (o ENTER).

Registro

Parámetro

AH

0Ah - código de la función

DS:DX

Puntero al buffer de memoria

Estructura del Buffer:

Posición

Significado

DS:DX

Cantidad máxima de caracteres admitida en el buffer (debe ser inicializada por el programador)

DS:DX + 1

Cantidad de caracteres leída (la escribe el DOS)

DS:DX + 2 y subsig.

Buffer donde se almacenan los caracteres leídos. La dirección del último es DS:DX + byte ptr (DS:DX)

En los dos primeros bytes, la cantidad de caracteres incluye al CR final. Suponiendo que el programador inicialice la posición de memoria DS:DX en 10h, el buffer tendrá un largo total de 16 caracteres, comenzando en DS:DX y finalizando en DS:DX + 0Fh, y podrá aceptar 13 caracteres más el de retorno.

DOS no se preocupa por borrar la parte del buffer que no escribe. Veamos en la tabla siguiente, para un buffer de 16 de largo qué caracteres encontramos luego de dos entradas sucesivas, la segunda más corta que la primera:

Dirección DS:DX + ...

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

primera entrada

10

0f

B

u

e

n

o

s

 

A

i

r

e

s

0d

?

segunda entrada

10

0a

C

o

r

d

o

b

a

0d

i

r

e

s

0d

?

Hay que notar que si bien esta función es muy cómoda, se queda esperando el caracter de retorno y hasta que este no llegue el programa no puede hacer otra cosa que... esperar!. En cambio, si se busca de a un caracter por vez, es posible hacer que el programa consulte el teclado como una de las tantas actividades posibles dentro de un mismo lazo.

Salida de string de caracteres, INT 21h - función 9h

Con esta función se envía un string de caracteres al dispositivo designado como salida standard (normalmente la pantalla). DOS permite redireccionar la salida a un archivo o a un puerto serial o LPT desde la misma línea de comandos, por lo que al usar esta función no hay garantías de que el string aparezca en pantalla. En realidad, esto también es válido para la entrada de caracteres vista en el punto anterior, aunque es mucho más frecuente redireccionar la salida que la entrada. Por ejemplo, el comando interno type archivo hará que el contenido del archivo sea visualizado en la pantalla, pero si agregamos un redirector con un dispositivo de salida "> LPT1", los caracteres del archivo serán direccionados al puerto de la impresora.

El string debe finalizar obligatoriamente con el caracter "$" (código ASCII 36). Los caracteres especiales como Bell, Backspace, CR, etc serán tratados como tales. Bell (ASCII 07) hace sonar una campana en el altavoz de la PC, CR vuelve al principio de la línea, Nueva_línea (ASCII 0Ah) pasa a la línea de abajo, etc

Al igual que en la lectura de strings, los parámetros son:

Registro

Parámetro

AH

09h - código de la función

DS:DX

Puntero al buffer de memoria donde reside el string

En lenguaje Assembly, un string para usarse con esta función puede ser declarado como sigue:

mensaje1    DB    "Todos los hombres de buena voluntad",0Dh,0Ah,"$"

y para utilizar la función 9h, el código a emplear sería:

display:

MOV

DX, offset mensaje1

 

MOV

AH,9

 

INT

21H

 

RET

 

 

 

Bibliografia

Moisés Burgos (2002). Interrupciones y manejo de archivo. [Documento en linea]. Disponible en:   http://members.tripod.com/~MoisesRBB/unidad6.htm [Consultado 08-01-06]