domingo, 6 de diciembre de 2009

Jugando a Core Wars [1° Parte/2]

Aqui veremos como funciona el juego Core wars, en el que hay que escribir un programa que intente eliminar a sus oponentes (para esto hay varios metodos... hacer que dividan por cero, que intenten ejecutar algo que no sea codigo,etc )

No voy a explicar como instalarlo, ya que hay muchos programas que sirven para jugar, puedes encontrar muchos aqui: http://homepages.paradise.net.nz/~anton/cw/corewar-faq.html#CoreWarSystems
En los repositorios de Ubuntu/Debian hay un paquete llamado corewars [ sudo apt-get install corewars ] que sirve perfectamente, pero es posible que despues no este en el menu, si es asi tendras que abrir un terminal y lanzar corewars

El lenguaje que se usa (llamado Redcode) es bastante parecido al Ensamblador, asi que aunque quien maneje este tendra mucho trabajo adelantado (se usan ADD's, MOV's, JMP's...), para est@s ultim@s hay que destacar que la sintaxis es mas parecida a la de AT&T que a la de Intel (por ejemplo en el ADD el primer argumento es la cantidad a añadir y la segunda donde se añadira), se explicara todo como si no se tuviera ninguna nocion de ensamblador.

Nota: desde ya mismo perdon por algunas licencias que me tomare para intentar hacer mas sencillo todo (como llamar "bytes" a las posiciones de memoria)

Como primer ejemplo utilizaremos el programa mas sencillo, llamado imp (de impulso):

    ;name Imp
    ;author Walter Hofmann

    mov 0,1

Si lo ejecutamos veremos que va llenando la memoria byte a byte (si se le puede llamar asi), uno de cada vez.

Veamos como es el codigo... lo que va despues de un ';' es un comentario (no tiene relevancia en el juego), algunos MARS (las maquinas virtuales donde suceden los "combates") buscan cierta informacion en los comentarios, por ejemplo los que despues de el ';' llevan la palabra "name", especifican el nombre del programa, y los que despues del ';' llevan "author", muestran el nombre del autor del programa.

Hasta ahora no paso nada que afectase a la "maquina" que ejecuta el programa, ahora viene lo divertido,el codigo MOV 0,1 copia la instruccion (MOV) que esta en la posicion 0 desde el codigo (el propio codigo) hasta la posicion 1 desde el codigo, la posicion de memoria siguiente, con lo que la instruccion se copia a la siguiente posicion y despues se ejecuta lo que haya en la siguiente posicion ( si, el mismo codigo otra vez ).

Para entenderlo mejor veamos rapidamente como funciona la maquina:

La memoria de la maquina es circular (no hay punto inicial ni final), es lineal (solo se puede ir hacia adelante o hacia atras) y es relativa (solo se puede especificar una posicion a partir de la actual, no se puede decir por ejemplo, la posicion 74).

El procesador de la maquina ejecuta una instruccion ( que siempre ocupan 1 "byte" ) y a menos que la instruccion implique un cambio en el flujo del programa (JMP, JNZ... ya se explicaran despues) a continuacion se ejecuta la siguiente, si no hay ninguna o la operacion no esta permitida (como una division por 0), el proceso "muere".

Entonces nustro ejemplo pasaria algo asi:

t=0

 ...
 ---------------
 | ???          |
 ---------------
 | MOV 0,1  | <- (Se va a ejecutar esto)
 ---------------
 | ???          |
 ---------------
 | ???          |
 ---------------

...


t=1 (despues de ejecutar la primera instruccion)


 ...

 --------------
 | ???         |
 --------------
 | MOV 0,1 |
 --------------
 | MOV 0,1 | <- (Se va a ejecutar esto)
 --------------
 | ???         |
 --------------
...


t=2 (despues de la segunda instruccion)


 ...

 --------------
 | ???         |
 --------------
 | MOV 0,1 |
 --------------
 | MOV 0,1 |
 --------------
 | MOV 0,1 | <- (Se va a ejecutar esto)
 --------------
 | ???         |
 --------------
 ...


Asi el programa va "haciendo el camino" y sigue hasta que algo lo detenga.

Ahora veamos algo un poco mas complejo.

            ;name Dwarf
            ;author A. K. Dewdney
dwarf  ADD #4, bomb
           MOV   bomb, @bomb
           JMP    dwarf

bomb  DAT #0

Aqui se introducen muchas mas posibilidades, empezando por esta:

bomb   DAT #0

Esto significa, hay un "byte" que no contiene ninguna instruccion, sino datos, y a esta posicion tiene la etiqueta "bomb" (para no tener que ver donde seria su direccion con cada nueva instruccion), su uso es bastante simple, si alguien intenta ejecutarlo el proceso falla, y se puede utilizar para almacenar datos (de ahi su nombre, DAT).

La segunda es:

dwarf  ADD #4, bomb

Un "byte" con la etiqueta "dwarf" y con la instruccion ADD, que añade el valor del primer argumento (en este caso 4), a lo que este en la segunda posicion (en este caso a lo que tiene la etiqueta "bomb" ).

Despues tenemos:

    MOV   bomb, @bomb

Como ya vimos en el primer ejemplo, la instruccion MOV copia lo que haya en el primer valor, en el segundo,pero en este caso el segundo valor se utiliza para indicar donde se va a copiar...me explico:

Hay tres grupos de formas de indicar una direccion, inmediata, directa e indirecta.

La inmediata es la que se toma partiendo de la posicion de donde se toma el valor, se indica con un '#' antes del valor (por ejemplo, el DAT o el primer valor del ADD).

La directa es la que se calcula partiendo de la posicion actual, se indica con un '$' o no añadiendo nada (por ejemplo, en el primer valor del MOV o en el JMP).

La indirecta, es la que se calcula partiendo de la posicion que indique el "byte" que se indique, dependiendo de si es el que indica el primero (campo A) o el segundo argumento (campo B) del "byte" se indican con un '*' o '@' respectivamente (se pueden hacer mas cosas, pero ya me estoy extendiendo demasiado por ahora)

Entonces     MOV   bomb, @bomb     copia lo que haya en la posicion "bomb" a donde apunte el campo B de "bomb".
Por ultimo...

          JMP  dwarf

La instruccion JMP salta a la posicion que se indique, en este caso la posicion con la etiqueta dwarf (el principio del codigo).
En resumen, lo que hace el codigo es:

- Añade 4 a la posicion que apunta "bomb"  (MOV #4,bomb)
- Copia "bomb" a la posicion que apunta (MOV bomb,@bomb)
- Vuelve al principio (JMP dwarf)

Asi que va llenando la memoria de DAT's, (si algun programa los intenta ejecutar falla), por ejemplo, contra un imp, podria ocurrir esto.

t=0
...
 ---------------
 | MOV 0,1  |
 ---------------
 | MOV 0,1  | <- (Se va a ejecutar esto)
 ---------------
 | ???          |
 ---------------
 | ???          |
 ---------------
...

t=1 (cuando el imp se copia a la siguiente posicion, y en el mismo "turno" el "bomb" del programa anterior se copia a la misma posicion)

...                                                          ...
 ---------------                                       ----------------
 | MOV 0,1  |                                        | MOV 0,1  |
 ---------------                                       ----------------
 | MOV 0,1  |                                        | MOV 0,1  |
 ---------------                          =>         -----------------
 | MOV 0,1  | <-  (Se va a ejecutar)    | DAT         | <-
 ---------------                                       ------------------ 
 | ???          |                                        | ???          |
 ---------------                                       -----------------
...                                                        ...

Esto es todo por ahora... hay una guia bastante completa en [http://vyznev.net/corewar/guide.html]

Suerte

No hay comentarios:

Publicar un comentario