Programación en Lenguaje Ensamblador

-El Verdadero Lenguaje de las Máquinas-

¿Qué es un Buffer de Datos?

–Cuando no tienes tiempo de esperar al mensajero–

Un buffer es una memoria en la que se almacenan datos de manera temporal para ser procesados. Se utiliza cuando los datos de entrada llegan a una mayor velocidad de la que podemos procesarlos o cuando llegan de manera tan irregular y esporádica que no resulta conveniente dedicar tiempo y recursos a esperarlos. Algunos ejemplos de buffers son los sistemas de entrada del teclado que almacenan las teclas presionadas, los buffers de video en los que se prepara el siguiente cuadro de animación para presentarlo en pantalla y otros tantos mas que como usuarios no creo que sean muy conscientes de lo que son o que hacen. Otra definición de buffer es la de una región de memoria que se usa como área de intercambio asíncrono entre procesos.

Como se han de imaginar, los buffers no nacieron junto con las computadoras sino que son una abstracción del mundo humano para explicar un concepto. De hecho una traducción un tanto oscura de la palabra Buffer es “Colchón” y se relaciona con los antiguos sistemas de reparto y entregas. Desde la época de los vaqueros y los inicios de la aviación los encargados de los sistemas de reparto y entregas descubrieron que podían ahorrarse mucho tiempo si en lugar de hacer que los mensajeros se detuvieran para entregar la mercancía colocaban uno de esos grandes colchones donde podían dejar caer los paquetes sin detenerse. De ese modo no era necesario dejar a alguien en la puerta esperando al mensajero y los empleados podían ir con toda calma y a una hora predeterminada a revisar estos buffers para ver si había llegado algún paquete. Un sistema muy parecido se utilizó en algunas fábricas y bodegas de muchos pisos en los que dejaban caer los productos por una especie de pozo vertical en cuyo fondo había un cojín y una pequeña puerta por la que se podían entregar los productos. En la actualidad las máquinas expendedoras automáticas usan buffers en los que dejan caer tanto el cambio en monedas como la mercancía de modo que el cliente no tenga que poner la mano y esperar a que estos caigan. Otro ejemplo mas sencillo es el viejo buzón de correos en el que el cartero puede dejar documentos y los habitantes pueden ir a revisarlos al regresar a su casa.

Los buffers son muy importantes y nos pueden ayudar a resolver una enorme cantidad de problemas que me llevaría toda la nota explicarles. Existen muchos tipos diferentes de buffers, hay algunos que funcionan como stacks y que sirven para recorrer estructuras de datos como grafos y árboles, otras trabajan como colas de procesamiento y nos dejan leer datos antes de que se pierdan, otros buffers mezclan datos de muchas fuentes y los combinan e incluso los buffers se relacionan con la recursión. Para hacer un buffer lo mínimo que necesitamos son 4 cosas. La primera obviamente es un espacio en memoria que vamos a usar como buffer. La segunda es un puntero o variable que almacene la dirección de memoria donde se encuenta, la tercera es un valor que indique la longitud máxima del buffer y la última es un índice o conjunto de índices que nos indiquen en qué localidad del buffer escribir los datos de entrada y leer los datos de salida. La combinación de la longitud máxima y los índices nos dirán si el buffer está lleno o vacio. Y aunque la administración de esta información suena muy complicada ya verán que existen muchas técnicas para manejarlos de manera eficiente por lo menos en ensamblador.

Problemas de los buffers:
Underflow y Overflow

Para los que no han leido las entradas mas elementales, el overflow es cuando hay demasiados datos en el buffer y los nuevos datos que llegan al no poder ser almacenados se pierden. El Underflow es lo contrario, cuando queremos obtener datos y el buffer está vacío. El Underflow es mas peligroso de lo que suena en ciertas aplicaciones como por ejemplo la grabación de datos en medios físicos como los discos. Si ocurre un buffer underflow la pieza puede quedar arruinada o en el caso de audio y video en tiempo real la comunicación puede presentar cortes. Es por eso que cada que se va a tener acceso al buffer ya sea para leer o escribir datos en él es necesario verificar que no van a ocurrir ninguna de estas dos condiciones. Pues si no se hace esta prueba no solo puede haber pérdidas de datos entrantes o cortes en el flujo de información sino que en casos de buffers muy mal diseñados puede haber problemas de sobreescritura que acaben por afectar otros datos importantes del programa y en casos muy dramáticos causar un fallo de protección de memoria o una caida completa del sistema. Les aconsejo que si consideran que el buffer puede ser peligroso lo coloquen en una región de la memoria alejado de los datos mas críticos.

Por suerte existe una técnica que nos puede evitar al mismo tiempo el problema del overflow, underflow y la sobreescritura. Esta técnica involucra máscaras de bit. El primer consejo es hacer que los buffers siempre tengan una longitud igual a una potencia de 2. Pueden ser 2,4,8,16,32,64,… Para el ejemplo vamos a tomar un buffer de 8 elementos. A partir de su dirección inicial, las siguientes 8 localidades se pueden numerar como 0,1,2,3,4,5,6 y 7 y los índices tanto de lectura como de escritura nunca deben de ser mayores que 7 ni menores que cero. Lo que cualquier programador que no sabe de ASM haría (y los que manejan leguajitos de ‘objetos y métodos’ ni siquiera harían esto) sería comprobar que ambos índices estuvieran dentro de ese rango antes de acceder al buffer y mandar un mensaje de error si esto no se cumple. Pues bien, como nosotros programamos en ensamblador nos basta con comprobar el estado de los bits que estén por encima de los 3 menos significativos. O lo que es lo mismo hacer una máscara AND con 0FCh (para índices de 8 bits). Si el resultado de esta operación es diferente de cero significa que los apuntadores están fuera del rango de cero a 8. Recuerden que los valores negativos tienen el bit mas significativo activado. De este modo si queremos detectar esta condición y encender una bandera que indique que hay un error basta hacer un AND seguido de un SETNZ. Si quisiéramos forzar a que los índices siempre se mantengan dentro del rango de 0 a 7 podemos hacerles un AND con un 3. Esto es especialmente importante para los buffers en forma de cola o los interesantísimos buffers circulares.

Voy a dejar el tema de los buffers circulares y de los buffers que funcionan como stacks y queues para otro dia porque son temas muy complicados para solo mencionarlos. De momento solo mencionaré que los buffers de Stack tienen un mismo índice que se usa tanto para leer como para escribir datos y que se incrementa o decrementa dependiendo de la operación que se haga. En los buffers de queue en los que los primeros datos en salir son los que mas tiempo llevan dentro del sistema el asunto es manejar dos índices uno para cada operación. Cuando ambos índices son iguales significa que el buffer está vacio y cuando la distancia entre ellos es igual a la longitud máxima del buffer este ya está lleno.

Para hacer buffers queue es necesario entender lo que es un buffer circular. Un buffer circular puede aceptar una cantidad infinita de datos pero solo puede recordar tantos datos como lo indique su longitud máxima. Los datos mas viejos se pierden por sobreescritura. Para hacer un buffer circular primero se define una extensión de memoria cuya longitud sea una potencia de dos y luego el puntero de entrada se mantiene dentro de ese rango por la fuerza por medio de máscaras AND. De ese modo no importa cuantas veces lo incrementemos ni durante cuanto tiempo el índice permanecerá dando vueltas en esa extensión de memoria sin salirse. Este tipo de buffers son muy importantes en la programación de videojuegos y en la animación de objetos articulados. Un Queue en realidad es un buffer circular que tiene un segundo puntero que va ‘persiguiendo’ al puntero de entrada de datos. Y es importante que un buffer queue sea en esencia un buffer circular porque he visto a muchos estudiantes que crean buffers capaces de caminar a todo lo largo de la memoria del sistema y aplastar por sobreescritura el resto de las variables cual si se tratara de las orugas de un tanque. Si el buffer queue se hace de manera circular se va a mantener en su lugar sin peligro de sobreescribir otras estructuras. Y esto es porque en los buffers queue los índices siempre se incrementan.

Por hoy no me voy a poner a trollear. Solo voy a comentar que voy a estar al pendiente de un juego que me dijeron que iba a salir publicado en este último cuarto del 2012. Espero que quienes lo están haciendo puedan terminarlo y recuperen su inversión, porque si siguen como hasta ahorra puede que a esta empresa le llegué su “Ultimo dia en La Industria”. Trollface.

Anuncios

octubre 18, 2012 - Posted by | Uncategorized | ,

2 comentarios »

  1. Qué explicación, por Dios! Eres un genio!

    Comentario por Juan Pablo | octubre 31, 2015 | Responder

  2. Que definicion del tema

    Comentario por Nelson encarnacion | marzo 12, 2016 | Responder


Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: