Le langage Red Code permet de programmer les adversaires qui
vont s'affronter dans la mémoire de l'ordinateur. Il est très
simple et proche d'un langage d'assemblage (il ressemble beaucoup
à l'assembleur des microprocesseurs de la famille x86 d'Intel).
La mémoire de l'ordinateur est constituée de 4096 cases (8000 dans
la version originale de Dewdne, ce nombre a été diminué pour une
raison expliquée par la suite). La mémoire est "bouclée" : la case
après la dernière (d'adresse 4095) est la première case (d'adresse
0). Ainsi, l'adresse 4100 est équivalente à l'adresse 4 (4100 - 4096 =
4) et -3 est équivalente à 4093.
Trois méthodes d'adressage de la mémoire sont possibles dans une
instruction :
Relatif : C'est le mode par défaut. Il est relatif
à la case de l'instruction en cours d'exécution. Par exemple, 3
pointe vers la troisième case après la case de l'instruction en
cours d'exécution.
Indirect : Est indiqué par un signe
@. L'adresse après le signe @ n'est pas l'adresse
pointée mais l'adresse de l'adresse pointée. Par exemple @3
pointe vers la case dont l'adresse est 3 cases après celle de
l'instruction en cours. Attention, la case contenant l'adresse
doit être du type DAT (cf plus loin) sans quoi, le programme
s'arrête sur une erreur d'indirection.
Immédiat : Est indiqué par un signe #
avant l'argument. Indique une valeur numérique, sans référence
d'adresse. Donc #3 est la valeur numérique 3.
Un programme est constitué d'une suite d'instructions contiguës en
mémoire. Chaque instruction occupant une case mémoire. Après
l'exécution d'une instruction, la suivante dans la mémoire est
exécutée (sauf si l'instruction est une instruction de saut). Les
instructions sont au nombre de 9 :
Instruction
Description
DAT A
C'est une déclaration de donnée. DAT 5 représente la valeur
5. Cette instruction n'est pas exécutable (si un programme doit
l'exécuter, il est arrêté). Elle ne comporte qu'un seul argument
(la valeur) qui n'a pas de type (ni relatif, ni indirect ni
immédiat).
MOV A B
Copie la case mémoire d'adresse A vers la case
d'adresse B. Par exemple, MOV 0 1 copie l'adresse relative 0 (donc la
case en cours d'exécution, soit l'instruction MOV 0 1 elle même) vers
la case suivante (la prochaine exécutée). Cette seule instruction
constitue un programme très court qui se recopie indéfiniment en
mémoire. Son premier argument peut être de tout type (relatif,
indirect ou immédiat) alors que son second ne peut être que relatif ou
indirect.
ADD A B
Ajoute le contenu de la case d'adresse A vers
la case d'adresse B. Son premier argument A peut être de tout type
(relatif, indirect ou immédiat) alors que le second, B, ne peut être
que relatif ou indirect. Cependant, les cases pointées doivent être du
type DAT car on ne peut ajouter que des valeurs numériques entre elles
(on ne peut ajouter une valeur à une instruction ou inversement). Si
ce n'est pas le cas, le programme s'arrête sur une erreur
arithmétique.
JMP A
Saut à l'adresse A. La prochaine instruction
exécutée le sera à cette adresse. L'argument A peut être relatif ou
indirect, mais pas immédiat.
JMZ A B
Saut à l'adresse A si le contenu de B est
nul. Les arguments A et B doivent être relatifs ou indirects, mais pas
immédiat.
JMG A B
Saut à l'adresse A si le contenu de B est
supérieur à zéro. Les arguments A et B doivent être relatifs ou
indirects, mais pas immédiat.
DJZ A B
Décrémente (soustrait 1) le contenu de A
puis saute vers la case B si le résultat est zéro. Les arguments A
et B doivent être relatifs ou indirects, mais pas immédiat.
CMP A B
Comparaison de A et B et saut de l'instruction
suivante s'ils sont différents. Les arguments peuvent être de tous
type.
IMP est un programme très simple, il ne comporte qu'une seule
instruction !
MOV 0 1
Il se recopie à la case mémoire suivante qui est exécutée
après cette instruction. On obtient donc un programme
auto-répliquant très simple qui se comporte comme un rouleau
compresseur et qui écrase toutes les cases de la
mémoire. Cependant ce programme est très primaire et ne peut
pour ainsi dire pas planter son adversaire dans la mesure où si
son adversaire est amené à exécuter une de ses instructions, il
se transforme lui même en IMP !
Ce programme (comme le précédent d'ailleurs) a été proposé par
Dewdney dans son premier article sur Core War (il est donc en quelque
sorte d'intérêt historique). Il est aussi très simple, mais toutefois
plus efficace que le précédent, dans la mesure ou il peut
effectivement planter l'adversaire.
JMP 2
DAT -1
ADD #5 -1
MOV #0 @-2
JMP -2
Ce programme est une sorte de bombardier : il boucle
indéfiniment et écrase une case de la mémoire avec un DAT
0 à chaque itération (pour planter un programme qui serait
amené à exécuter cette instruction) . L'adresse est incrémentée
à chaque boucle de 5 cases (ADD #5 -1) de manière à
balayer la mémoire. DAT -1 est le compteur de l'adresse
de la case visée par le projectile, l'instruction MOV #0
@-2 y fait référence comme adresse de destination.
Ce programme est aussi un exemple tiré du premier article de
Dewdney. Son intérêt est qu'il se reproduit (de manière plus efficace
que IMP). Il doit être vu comme une partie de code d'un programme plus
vaste (qui comporterait entre autre une fonction vraiment offensive)
ayant la possibilité de se reproduire en mémoire.
Dans un premier temps, il se reproduit par copie des cases mémoire
de son propre code, puis il saute à sa copie.
Le plus simple pour étudier ces programmes est de les charger dans
le moteur de Core Warrior et de les exécuter pas à pas pour voir
l'effet de chaque instruction.
Vous en savez maintenant assez pour créer vos premiers guerriers !
Pour ce faire, je ne saurait que vous recommander d'installer et
lancer l'éditeur de Core Warrior (lancé par le script moteur ou
moteur.bat).