jueves, 10 de diciembre de 2009

Jugando a Core Wars [2° Parte/2]

Sigamos con el Core Wars...
Resumiendo, lo que vimos hasta ahora fue:

    ;Comentarios
    ;name nombre del programa
    ;author autor
    MOV A,B ;Copia A en B
    ADD A,B  ;Añade A a B
    JMP A     ;Se salta la instruccion A
    DAT A,B ;Un espacio para datos

Formas de indicar una direccion:

-Inmediata, por de la posicion donde esta el valor, se indica con un '#'
-Directa, por la posicion actual, se representa con '$' (o sin nada)
-Indirecta, por el valor de la posicion indicada, se indica con un '*' si es el primer campo (A), o con '@' si es el segundo campo (B)

Pero hay mas formas de indicar una direccion de forma indirecta:

- La del campo A, restandole 1 antes, '{'
- La del campo B, restandole 1 antes, '<'
- La del campo A, sumandole 1 despues, '}'
- La del campo B, sumandole 1 despues, '>'

Por ejemplo, se podria modificar el programa "dwarf"

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

bomb  DAT #0


Haciendo que llene todos los espacios de memoria 1 a 1, en vez de cuatro en cuatro, y de paso eliminamos una instruccion (con lo que el programa es mas rapido)


dwarf  MOV   bomb, >bomb
          JMP    dwarf

bomb  DAT #1


Veamos las diferencias, la primera es que ya no esta la instruccion ADD por que lo que hacia (cambiar el valor de "bomb" para evitar estar siempre "golpeando la misma zona")ahora lo hace el MOV.
La segunda es el campo B de la instruccion MOV incrementa el valor del campo B de "bomb" uno de cada vez (por el '>').
La ultima es que el valor al que apunta "bomb" al principio es el siguiente ('#1'), ya que al no haber ADD y a que el incremento es posterior, si fuera el mismo ('#0'), se sobreescribiria, algo totalmente inutil.

Ahora algo mas complejo... aunque no por ello util:

      SUB #7,inst ;Para reajustar el puntero de instruccion
      SUB #6,pos ; Esto tambien
      MOV >inst,>pos
      SEQ inst,inst+1 ;Aqui esta el problema XD
      JMP -2
      JMP -14 ;Al proximo paso
pos  DAT #-9
inst  DAT #0 ;Los valores que quedaran despues de copiarse a si mismos
       DAT #2

Como se puede ver aqui hay instrucciones nuevas:
-La primera es SUB (de substract, restar ), funciona igual que el ADD, pero en vez de sumar, resta (logicamente es igual que hacer ADD de un numero negativo)
-La otra es SEQ (skip if equal, saltar si es igual), compara las dos instucciones y si son iguales se salta la siguiente instruccion

Veamos que hace el codigo entonces :
El DAT con la etiqueta pos, indica la posicion a donde se va a copiar, y el de la etiqueta inst, la instruccion que se va a copiar.
El DAT siguiente al de inst tiene siempre el valor #2, esto servira para comprobar si se acabo de copiar todo el codigo.

-Resta 7 al DAT que indica la instruccion a copiar (para que apunte al principio del codigo)    [ SUB #7,inst ]
-Resta 6 al DAT que indica donde se copiara la instruccion (para que apunte a la proxima seccion donde se copiara) [ SUB #6,pos ]
-Copia la instruccion a la que apunta inst a la posicion que indica pos, y incrementa en 1 los dos (para que apunten al siguiente) [ MOV >inst,>pos ]
-Si inst es igual a lo que hay en la siguiente posicions, se salta la siguiente posicion [ SEQ inst,inst+1 ]
-Vuelve atras 2 instrucciones [ JMP -2 ]
-Vuelve atras 14 instrucciones (pasa al bucle siguiente) [ JMP -14 ]

Es decir, que se copia todo hacia atras, hasta que acaba y salta hacia atras, para continuar copiandose.La utilidad que tiene esto es poca, con un minimo cambio en cualquier parte del codigo que se este ejecutando, el programa falla.

Las opciones para cambiar el flujo del programa son:

-SEQ (explicado anteriormente)
-SNE (funciona al reves que SEQ) (Skip if Not Equal, saltar si no es igual)
-SLT (se salta la siguiente instruccion si el campo A es menor que el campo B) (Skip if Less Than, saltar si es menos de)

-JNZ, si el valor del campo A es distinto de 0, se salta a la posicion que indica el campo B (Jump if Not Zero, saltar si no es cero)
-JZ, como JZN, pero si el valor de A es 0 (Jump if Zero, saltar si es cero)
-DJN, como JNZ, pero decrementa previamente el valor de A (Decrement & Jump if Not zero, decrementar y saltar si no es cero)

-SPL, se crea un segundo proceso que empieza en la posicion indicada (Split, separar)

La unica que introduce algo nuevo es SPL, veamos un ejemplo:

    SPL 0
    MOV 0,1

- SPL 0, crea un proceso mas, que seguira en la misma instruccion (si, asi continuamente)- MOV 0,1 ... un clasico imp (como el primero de todo)

Lo que hace es generar muchos procesos, ejecutando todos el codigo del imp
Si lo ejecutamos veremos que aunque al principio el conjunto de imps avanzan relativamente rapido, poco a poco van mas lentos, esto es por la forma que hay de repartir el tiempo entre los procesos:

Durante el turno de cada programa se ejecuta un proceso suyo y este no se volvera a ejecutar hasta que lo hayan hecho el resto

Esto significa que cuantos mas procesos haya para el programa, mas habra que esperar para que se repita el mismo proceso (por esto y por otras cosas suele haber un limite de procesos por programa)

Ya no se me ocurre nada mas que pueda hacer falta para escribir un programa de Core Wars, asi que eso es todo por ahora.

Quien no tenga problemas con el ingles tiene un buen tutorial en [ http://vyznev.net/corewar/guide.html ]

Actualizacion: Uno mas ( este no lo explicare :)}, es bastante sencillo )

    ;name Code Runner
    ;author Kenkeiras

    ADD #4,3
    SPL >2
    JMP -2
    DAT #1,#1

Suerte

No hay comentarios:

Publicar un comentario