Introducción a la Entrada/Salida (E/S) Programada
La arquitectura MIPS emplea un sistema de E/S asignada en memoria. Esto significa que se utilizan direcciones específicas dentro del espacio de direcciones para referirse a los registros de los dispositivos periféricos. La dirección base para la E/S mapeada en memoria es 0xffff0000. En este contexto, nos centraremos en dos periféricos fundamentales: el teclado y el monitor. Los registros de datos para estos dispositivos se encuentran en las direcciones 0xFFFF0004 y 0xFFFF000C, respectivamente.
En esta sesión, utilizaremos la técnica de E/S por encuesta. Esta técnica implica la verificación periódica del estado de un dispositivo para determinar si está listo para una operación de entrada o salida.
Bucle de Encuesta para Lectura de Teclado
El bucle de encuesta para la lectura de un carácter desde el teclado se implementa de la siguiente manera:
li $t0, 0xffff0000;
ckready:;
lw $t1, 0($t0);
andi $t1, $t1, 1;
beq $t1, $0, ckready;
Bucle de Encuesta para Escritura en Monitor
El bucle de encuesta para la escritura de un carácter en el monitor se puede implementar de la siguiente manera:
li $t0, 0xffff0000;
xready:;
lw $t1, 8($t0);
andi $t1, $t1, 1;
beq $t1, $0, xready;
Subrutinas para Manejo de Cadenas
1. Subrutina ReadString
Esta subrutina lee los caracteres ingresados por teclado y los almacena en la memoria a partir de la dirección especificada en el registro $a0. La cadena de entrada finaliza cuando se presiona la tecla ESC (código 0x3b). La subrutina devuelve en el registro $v0 el número total de caracteres leídos.
2. Subrutina PrintString
Esta subrutina escribe en la pantalla la cadena de caracteres que comienza en la dirección de memoria indicada por el registro $a0. La longitud de la cadena se encuentra almacenada en el registro $a1.
3. Programa Principal
El siguiente programa utiliza las subrutinas ReadString y PrintString para leer datos desde el teclado y mostrarlos en la pantalla.
Código en Ensamblador MIPS
.text
.globl main
main:
la $a0, cadena
jal readString
addi $a1, $v0, 0
jal printString
addi $v0, $0, 10
syscall
readString:
li $t6, 0xffff0000 # Control teclado
li $t7, 0xffff0004 # Datos teclado
addi $t0, $0, 0 # Control teclado
addi $t1, $0, 0 # Datos teclado
addi $t2, $0, 0 # Número de caracteres
addi $t3, $0, 0x3b # Tecla ESC
add $t4, $0, $a0 # Dirección donde guardar el string
ckready:
lw $t0, 0($t6)
andi $t0, $t0, 1
beq $t0, $0, ckready
lb $t1, 0($t7)
beq $t1, $t3, salir_ck
addi $t2, $t2, 1
sb $t1, 0($t4)
addi $t4,$t4,1
j ckready
salir_ck:
addi $v0, $t2, 0
jr $ra
printString:
li $t6, 0xffff0008 # Control pantalla
li $t7, 0xffff000c # Datos pantalla
addi $t0, $0, 0 # Bit control pantalla
addi $t1, $a0, 0 # Puntero al string
addi $t2, $0, 0 # Número de caracteres
xready:
lw $t0, 0($t6)
andi $t0, $t0, 1
beq $t0, $0, xready
lb $t3, 0($t1)
sb $t3, 0($t7)
addi $t2, $t2, 1
beq $t2, $a1, salir_x
addi $t1, $t1, 1
j xready
salir_x:
jr $ra
.data
cadena: .word 0,0,0,0,0,0,0,0
Entrada/Salida por Interrupciones
En los procesadores MIPS, una parte de la CPU llamada coprocesador 0 maneja la información necesaria para los programas que tratan excepciones e interrupciones. Los registros relevantes para el procesamiento de excepciones e interrupciones (IRQ) en el simulador son:
- Registro EPC (Exception Program Counter): Es el registro 14 del coprocesador 0. Contiene la dirección de la instrucción que se estaba ejecutando cuando ocurrió la excepción.
- Registro Status: Es el registro 12 del coprocesador 0. Contiene la máscara de IRQs y los bits de autorización.
- Campo Máscara de IRQs: Contiene un bit para cada uno de los cinco niveles de interrupción de hardware y tres de software. Un bit en 1 habilita la interrupción en ese nivel.
- Bits de Núcleo/Usuario y Permiso de IRQ: Los seis bits menos significativos forman una pila para los bits de núcleo/usuario y permiso de IRQ. El bit de núcleo/usuario indica si el programa estaba en el núcleo del sistema operativo (0) o en modo usuario (1) durante la excepción. El bit de permiso de IRQ habilita (1) o deshabilita (0) las interrupciones.
- Registro Cause:
- Bits Pending Interrupts: Los ocho bits corresponden a los ocho niveles de IRQ. Un bit se pone a 1 cuando ocurre una interrupción en su nivel y no ha sido atendida.
- Campo Exception Code: Describe la causa de la excepción. Un valor de 0 indica una interrupción externa. La rutina de manejo de IRQs debe determinar la causa encuestando a los dispositivos manejados mediante IRQs.
Pasos del Procesador al Aceptar una Interrupción
- Después de una IRQ, el registro EPC contiene la dirección de la instrucción en ejecución durante la IRQ.
- Los 6 bits menos significativos del registro Status se desplazan dos bits a la izquierda. Los bits actuales se convierten en previos, los previos en antiguos y los antiguos se descartan.
- El procesador salta a la dirección 0x80000080 (espacio del núcleo), donde se encuentra la rutina de atención a la IRQ. Esta rutina determina la causa de la IRQ según el registro Cause y salta al manejador adecuado en el sistema operativo.
- Una vez resuelta la tarea, se restaura la máscara de interrupción y los bits de núcleo/usuario previos en el registro Status con la instrucción rfe (return from exception).
- La rutina de interrupción devuelve el control saltando a la instrucción siguiente a la que causó la excepción.