martes, 30 de diciembre de 2008

Gestión de Entrada/Salida

Introducción

Los sistemas operativos brindan cuatro funciones básicas: Intérprete de Comandos, Gestión de la Memoria, Gestión de Entrada/Salida y Sistema de Archivo. En este artículo analizaremos la función de administración de Entrada/Salida por medio de ejercicios de programación que nos mostrarán en la práctica cómo funciona el Sistema Operativo. Para realizar estas prácticas, utilizaremos el lenguaje ensamblador ya que es en ese lenguaje en el que está programado el núcleo central o kernel del sistema operativo.

En la Práctica

Si observamos la Fig. 2 del artículo Concepto de Sistema Operativo , notaremos que el BUS del sistema permite interconectar todos los componentes de la PC, por esto se dice que la PC tiene una arquitectura de BUS. El bus no es otra cosa que cables (o pistas de cobre) que pueden tener el valor 0 o 1 (+5 Volts o 0 Volts).

El bus está organizados en tres grandes grupos:

- El bus de datos.
- El bus de direcciones.
- El bus de control.



Fig. 1 El Chip 8253 de Intel

Nota: Desde el punto de vista de las señales eléctricas, el bus dispone de tres conjuntos de líneas: Datos, Direcciones y Control; sin embargo, las rutinas del sistema operativo y los programas pueden solamente acceder a dos: Dirección o Puerto y Datos. Las señales de control tienen que ver con operaciónes que se realizan a nivel de hardware, tales como la habilitación y la señal de escritura o de lectura de un chip. Habitualmente, los dispositivos de E/S utilizan para sus operaciones un conjunto de direcciones que sirven para distintos propósitos (entrada/salida de datos, configuración, control, etcétera). Por esta razón, se habla de dirección de base, y se refiere a aquel puerto que da comienzo a la sucesión de direcciones propias del dispositivo.

Las computadoras personales o PC tienen dos circuitos temporizadores; por un lado, el Circuito Integrado 8253 de Intel que es un temporizador/contador y el 6818 de Motorola que es un reloj de tiempo real. Si observamos detenidamente la Fig. 2 en el artículo Concepto de Sistema Operativo , podremos notar el “temporizador” y el “reloj de tiempo real” conectados al BUS de la PC.

Durante el proceso de inicio de la PC (boot-up) la fecha y hora se obtienen del reloj de tiempo real M6818. A partir de ese momento, la fecha y hora son mantenidas por medio de los pulsos generados por el chip 8253, hasta que se apaga la PC.

Fig 2. Los “Relojes” de la PC

Una de las funciones que cumple el 8253 (actualmente el 8254 cumple estas funciones) es la de generar el sonido en el parlante de la PC. Para esto debemos “programar” el 8253 para que divida la frecuencia de base que recibe de un oscilador a cristal (1.192,180 KHz.) en su registro de 16 bits.

Fig. 3 El Registro de Control del 8253

Para programar un contador del 8253 hay que enviar primero una palabra de control y, después, un valor de cuenta inicial. Los contadores se seleccionan con las líneas A0 y A1; el valor A0=A1=1 selecciona la escritura de la palabra de control (en la que se identifica el contador implicado). Por tanto, el 8253 ocupa normalmente 4 direcciones de E/S consecutivas ligadas a los contadores 0, 1, 2 y al registro de la palabra de control. Para enviar la cuenta inicial se utiliza simplemente el puerto E/S ligado al contador que se trate. El formato de la palabra de control puede observarse en la Fig. 3, a partir de esta palabra de dos bytes se puede establecer el canal, el modo, el formato de datos y los datos a enviar.

Un Ejemplo Concreto

Tal como mencioné en otros artículos relativos al lenguaje ensamblador y DOS, todos los ejemplos que les presento se pueden realizar en cualquier PC de las actuales. Si, con Windows Vista y XP también, y funcionan tanto en equipos portátiles o de mesa. En el caso de los ejemplos de este artículo, los realicé en una Notebook Presario 3000 que corre Windows XP SP 2.

Como ejemplo vamos a programar el canal 2 del 8253 para producir una señal de onda cuadrada con los siguientes parámetros: Canal 2, Modo de Operación 3, Datos Enclavados (latched), LSB Primero (byte menos significativo), MSB (byte mas significativo) después, Datos en formato BCD (binario codificado en decimal)

Un término que es conveniente definir en este momento es el de LATCH (cerrojo) que corresponde a un concepto de electrónica digital que presentaré en otro artículo con ejemplos y circuitos prácticos. Pero para una definición rápida, podemos pensar en el LATCH como un conjunto de 8 bits que pueden ser establecidos (set) y mantener (hold) el dato binario que le cargamos; y luego podemos quitar (reset). En el caso del 8253 que como sabemos tiene un contador de 16 bits, recibe dos bytes (8 bits) en la misma dirección y los mantiene gracias al LATCH.

Fig. 4 Definición del Comando

Algunos puntos a tener en cuenta:

Cada canal temporizador del 8253 puede ser programado en uno de seis modos: Modo 0 a 5.

Todos los canales temporizadores realizan conteos o tareas de temporizado designados en forma simultánea e independientes entre sí.

Los canales 0 y 1 son inicializaos por el BIOS y son utilizados para funciones del sistema; por lo tanto, el usuario no debe interferir con estos canales.

Solamente el canal 2 está disponible para aplicaciones del usuario.

Cada canal opera por medio de un registro contador de 16 bits que disminuye su valor en uno por cada ciclo de la señal de 1,19 MHz del reloj.

Para generar la onda cuadrada en la salida del canal 2:

- El valor B7 se envía al puerto 43h (registro de comando)
- El LSB se envía al puerto 42h (latch)
- El MSB se envía al puerto 42h (latch)

Iniciamos debug desde una sesión DOS Inicio/Ejecutar – command – Aceptar, si no recuerda estos pasos, repase los artículos: Ensamblador (Entrega 1) y Ensamblador (Entrega 2).

1) En la línea de comandos de debug escribimos a (ensamblar)

-a

2) Luego cargamos las siguientes instrucciones


3) Retornamos a la línea de comando de debug y escribimos g 100 (go es el comando para ejecutar el código)

-g 100

4) Aplicamos p (ejecutar paso a paso)

5) Al llegar a la línea 110, luego de aplicar p, se activa el sonido

6) Si continuamos aplicando p, al llegar a la línea 118 y aplicar p, se desactiva el sonido

7) El programa finaliza y para salir de debug aplicamos el comando q (quit).

Explicación Detallada

1) Enviamos la palabra B7 al puerto de control 43h del 8253, como sabemos, no se puede realizar una operación de salida a puerto o OUT en forma directa y siempre debemos “cargar” previamente un registro de la CPU. Recordemos que B7 significa que el controlador operará a través del temporizador 2 (o canal 2), en Modo 3 y que espera los datos en BCD.

MOV AL,B7
OUT 43,AL

2) Enviamos los datos en formato BCD, primero el LSB (byte menos significativo) que en este caso es 72h y luego se envía el MSB (byte mas significativo) que es 45h.

MOV AL,72
OUT 42,AL
MOV AL,45
OUT 42,AL

3) Para activar el 8253, se lee por medio de la instrucción IN el puerto 61h, se complementa con el valor 3 y luego se envía al mismo puerto 61h (de datos).

IN AL,61
OR AL,3
OUT 61,AL


4) De esta forma queda activado el sonido ya que el 8253 mantendrá la generación de la onda cuadrada de la frecuencia especificada hasta que se le ordene que se detenga.

5) Para desactivar el 8253, se lee por medio de la instrucción IN el puerto 61h, se cambian los bits por medio de XOR con el valor 3 y luego se envía al mismo puerto 61h (de datos).

IN AL,61
XOR AL,3
OUT 61,AL


6) Y de esta forma se detiene el sonido; luego, para terminar el programa se usa la interrupción 21 en forma estándar.

MOV AX,004C
INT 21


7) La instrucción NOP significa no operar y es una instrucción que ocupa un lugar en la memoria pero que es ignorada por la CPU.

Importante

Si les resulta mas fácil inicializar el contador en binario en lugar de hacerlo en BCD pueden cambiar el último bit de la palabra de comando, y enviar el valor de la frecuencia diréctamente en binario. Para esto, en lugar de B7 enviaremos B6 al puerto 43h del 8253. En este caso, el cálculo de frecuencia del sonido es como sigue:

Velocidad del Reloj/Frecuencia del Sonido

Supongamos que deseamos una frecuencia de 600 Hz.

1.192,180 kHz. / 600 Hz = 1.989 (07C5 en hexadecimal)

Recordemos que se envía primero el byte menos significativo al latch y luego el mas significativo.

MOV AL,B6
OUT 43,AL
MOV AL,C5
OUT 42,AL
MOV AL,07
OUT 42,AL

Prácticas Adicionales

Prueben realizar los siguientes programas en archivos de texto, por ejemplo Suena.txt y Nosuena.txt. Para ensamblarlos escriban en la línea de comando de DOS c:\>debug < suena.txt y generaran el programa suena.com (repase el proceso de ensamblado en el artículo: Lenguaje Ensamblador (Entrega 3)) . Estos programas activan (suena.com) y desactivan (nosuena.com) el sonido.

NSuena.com
A
MOV AL,B7
OUT 43,AL
MOV AL,72
OUT 42,AL
MOV AL,45
OUT 42,AL
IN AL,61
OR AL,3
OUT 61,AL
MOV AX,004C
INT 21
NOP
NOP
NOP

RCX
16
W
Q

NNosuena.com
A
MOV AL,B7
OUT 43,AL
MOV AL,72
OUT 42,AL
MOV AL,45
OUT 42,AL
IN AL,61
XOR AL,3
OUT 61,AL
MOV AX,004C
INT 21
NOP
NOP
NOP

RCX
16
W
Q

Este artículo forma parte de una serie en los que vamos a explorar las funciones de los sistemas operativos con la acostumbrada modalidad de ensuciarnos las manos o “hands on”. Esto significa que realizaremos ejercicios de programación concretos y significativos que nos permitirán comprender al sistema operativo por dentro.

Que tengan un gran día,

Sergio Otaño

4 comentarios:

Miguel dijo...

Tremendo articulo, muchas felicidades

Miguel dijo...

Tremendo articulo, muchas felicidades

Anónimo dijo...

a mi me sale un errar "the NTVDM cPU has encountered an ildegal instruction.
CS:fef0 IP:f02c OP:63 74 6f 72 79 Chooose CLose to terminate the application"

y ps solo me funciono una vez

Sergio Otaño dijo...

NTVDM es como su nombre lo indica una maquina VIRTUAL y el programa busca acceder a un puerto REAL. Puedes probar con una maquina antigua o ingresando solo al simbolo del sistema. Tambien puedes probar ejecutar las instrucciones desde Debug, una a una y seguramente lo lograras.