Programación en Lenguaje Ensamblador

-El Verdadero Lenguaje de las Máquinas-

Corazones y Estómagos (Parte 1 de 3)

–Procesamiento de Mensajes en Windows–

Una de las diferencias mas importantes entre las aplicaciones gráficas y las de consola(chafas porque las buenas tambíen lo tienen) es precisamente la Interactividad. Muchos programadores (chafas) de la vieja época no comprendían como una ventanita podía responder a los clicks del ratón, reconstruir texto cuando uno cambiaba las dimensiones de una ventana ni mucho menos enterarse cuando ocurría algún evento externo como un reset o un ‘system shutdown’. Por culpa de estos desarrolladores estúpidos que creían que las estructuras cíclicas solo servían para imprimir las tablas de multiplicar fue que se extendieron tan rápidamente entornos de desarrollo para retrasados como todos los de la familia ‘visual’ y sus similares. Esto, sumado a la ineptitud de la mayoría de los pseudomaestros de Ingeniería en computación que no salían del 8086 para DOS no solo fue un duro golpe contra la Programación en Ensamblador, sino contra casi toda la programación seria (incluida la de C) que había en ese entonces. Por no mencionar que a partir de entonces los lamers se volvieron económicamente muy fuertes. Bueno, mejor hablemos mas de programación y menos de cosas escatológicas:

Los poetas que le hacen al programador acostumbran decir que el ciclo de mensajes de una aplicació en Windows es como un corazón. Sin embargo, yo le hayo mas parecido a un estómago. De hecho, la administración de mensajes de una aplicación en Windows es sorprendentemente parecida a un Sistema Digestivo. Pues una parte es la que se traga los mensajes, otra que los procesa conforme llegan y otra por donde los resultados son expulsados y enviados a un lugar del que no sabemos nada. Esta entrada se concentra en el ciclo de recepción de mensajes que en su análogía con el aparato digestivo sería la boca:

Lo siguiente de la llamada a UpdateWindow, es un ciclo infinito que llama sucesivamente a GetMessage, TranslateMessage y DispatchMessage. En cada vuelta, este ciclo lee un mensaje del Message Queue, lo traduce y lo despacha para luego repetir el mismo proceso hasta que encuentre el mensaje de terminación. Si leyeron la nota del Mensaje En Una Botella, este ciclo es equivalente a meter la mano al mar, sacar una de esas botellas que vienen flotando hacia nosotros, abrirla y tomárnosla. Ahora veamos en detalle cada una de estas partes:

*mas_mensajes: es una etiqueta que indica que ahí comienza el ciclo de mensajes. Para quien tenga experiencia en programación (o crea que la tiene) esto es equivalente a un DO WHILE. De hecho el ciclo termina con la instrucción jmp mas_mensajes

*GetMessage.- Esta función de la API de Windows es la que saca la botella del mar. Tiene 4 parámetros. El primero es lpMsg que es la posición de memoria de una estructura de mensaje. O donde vamos a poner la botella en cuanto las saquemos del agua. El segundo es hWnd que es el handle de la ventana que la recibe. Si este valor es cero, podemos obtener todos los mensajes de todas las ventanas que dependen del proceso que llama la función. No es posible interceptar los mensajes que van a otras ventanas (al menos no de esta manera). Los últimos 2 argumentos son 2 enteros que indican el rango de mensajes que esperamos recibir. Si estos parámetros son cero, entonces recibiremos todos los mensajes que nos manden.

Hay un detalle interesante en esta función, y es que hay una botella con valor especial que es detectada instantaneamente por GetMessage. Este mensaje es WM_QUIT. En cuanto este mensaje es recogido el valor de retorno es CERO. Esta es la condición de terminación del ciclo de mensajes. En cuando se detecta este cero, uno sale del ciclo principal. Para salir de un ciclo infinito es necesario saltar hacia afuera de este. El código que detecta este cero y sale del ciclo son el par de instrucciones OR EAX, EAX y JZ NO_MENSAJE. Mas adelante detallaré el uso de estas instrucciones.

*TranslateMessage.-Esta función en realidad no tiene uso y lo dejé para no alterar el código original de Iczelion. Esta función toma como argumento la dirección efectiva de la estructura de mensaje (no olviden el uso de LEA para obtener la posición absoluta). Y lo que hace es traducir el valor de la Tecla virtual en un signo ascii legible. Para Windows, hay diferencia entre una tecla y el valor ascii que esta representa.

*DispatchMessage.- Toma como parámetro la posición de una estructura de mensajes para mandarlo directo y sin escalas al Window Procedure. Volviendo al Aparato Digestivo, esto es equivalente a tragar el contenido de la botella y mandarlo al estómago.

*Luego de la llamada a DispatchMessage, sigue el salto incondicional JMP MAS_MENSAJES y la etiqueta NO_MENSAJE. En esta etiqueta es donde caemos si la función GetMessage nos retorna un CERO. A partir de aquí ya estamos cerca de la salida del programa.

*Las funciones LEAVE y RET 10h indican que ya se acabó la función WinMain. Y como recordarán en notas anteriores. Lo que sigue es ExitProcess y el fin del programa. Lo que sigue en el código es la CALLBACK PROCEDURE o Window Procedure, que es la parte mas interesante del aparato digestivo de una ventana.

De acuerdo, acabo de describirles como hace una ventana para tomar los mensajes, pero aún no se explica como los procesa. Esto es apenas la boca. Algunos detalles importantes sobre esta parte del código son las siguientes:

GetMessage bloquea la ejecución.- Una vez que llamamos a la función GetMessage, la ejecución del programa se detiene y no va a continuar hasta que no le llegue un mensaje. Aunque esto no afecta a las demás aplicaciones. Sin embargo existen otras funciones como PeekMessage que no la bloquean. Peekmessage es muy importante para aquellos que se interesan en programar juegos de video porque un verdadero juego no se puede bloquear en espera de un mensaje.

TranslateMessage solo trabaja con signos.- En Windows hay algo llamado Teclado Virtual. Es un arreglo de 255 valores que identifican de manera única no solo a las teclas que imprimen letras, sino que también a las teclas de control, flechas, ¡E incluso los botones del ratón!. TranslateMessage filtra estos valores y se queda solo con aquellos a los que corresponde un byte alfanumérico. Por cierto, los programadores aficionados de juegos usan esta función para leer los controles del juego, sin embargo esto no tiene tan buena respuesta como la que ofrece DirectInput y es muy común que en estos juegos no se puedan presionar mas de 4 o 5 teclas simultaneamente.

Aquí se acaba el show por hoy, lo que sigue es ver como se procesan y gestionan los mensajes que acabamos de recibir. Espero que este blog le sirva a alguien para algo y no solo sirva para insultar lamers.

Anuncios

enero 28, 2009 - Posted by | Uncategorized

Aún no hay comentarios.

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: