martes, 13 de mayo de 2008

Una rutina elegante

Definiendo el problema

El problema consiste en hacer mirroring de 4 nibbles W X Y Z, situados en dos bytes en ram en la forma WX e YZ. El resultado deben ser dos bytes de la forma ZY y XW, vamos, que los cuatro nibbles se han dado la vuelta por completo.

Normalmente leeríamos los bytes en el registro A, enmascararíamos para quedarnos con el nibble inferior, rotaríamos, leeríamos el nibble superior, guardaríamos los nibbles en variables auxiliares y escribiríamos todo después de haber hecho las rotaciones "a mano". Sin embargo yo quería hacerlo más elegantemente, de manera más rápida y, obviamente, con el menor número de instrucciones posibles.

Resolviendo el problema

Empecé por usar HL y DE como punteros, de forma que HL apuntase al primer byte (el compuesto por los nibbles WX) y DE al segundo byte (compuesto por los nibbles YZ). A continuación empecé a escribir instrucciones en la libreta a ver qué pasaba. La primera fue RLD.

¿Qué hace estra instrucción? Rota a la izquierda 4 bits de un número de 12 bits formado por los 4 bits inferiores del registro A y el byte contenido en la dirección de memoria apuntada por HL... Vale, pongamos un ejemplo :D

Si A vale $7E (en hexadecimal) y la posición de memoria apuntada por HL vale $38, al hacer RLD rotamos el número $E38 cuatro bits hacia la izquierda, resultando el número $38E, que vuelve a situarse en los 4 bits inferiores de A y en la posición de memoria apuntada por HL, es decir A valdrá $73 y la posición de memoria apuntada por HL $8E (ojo, siempre que sea RAM, que si no no variaría).

La solución

A partir de aquí el resto de la rutina salió solo. Como quería ir leyendo y escribiendo del contenido de las posiciones de memoria apuntadas por HL y DE se me ocurrió seguir con EX DE,HL instrucción que intercambia el valor de ambos registros. Así, después de un rato emborronando las páginas de mi libreta mientras iba en el metro, salió la siguiente rutina que realiza el trabajo deseado:

RLD
EX DE,HL
RRD
EX DE,HL
RLD
EX DE,HL
RRD
EX DE,HL
RLD

Donde RRD hace lo mismo que RLD pero desplazando a la derecha en lugar de a la izquierda. El valor que tuviera el registro A al comienzo del algoritmo seguirá siendo el mismo al final, igual que los valores de DE y HL, por lo que para utilizar esta rutina no hace falta salvar el contenido de ningún registro.

Y ahora me diréis "vale pero, ¿para qué sirve esta rutina?". Imaginad que tenéis una tabla formada por nibbles y que queréis darle la vuelta, es decir, obtener la misma tabla pero en sentido inverso. Por ejemplo para obtener la imagen especular de un puzzle del QBIQS... :)

¿A que queda elegante?


No hay comentarios: