snroettg@faui09.informatik.uni-erlangen.de (Stefan Roettger) (02/12/91)
Hi friends!
Here are the Core War standards as promised.
Foreword:
In a Core War battle two programs written in the
pseudo-assembly language REDCODE are run against each other
on a simulation enviroment called MARS (Memory Array
Redcode Simulator). The aim of each program is to bomb its
opponent. Obviously the Warrior that survives and kills its
foe first is the winner. The thrill of the game is, that
many possible strategies such as defensive, self-repairing,
small-but-quick and others can be programmed and of course
it's great fun to compare your own warriors with those of
your friends!
Disclaimer: Core War is not in the slightest way viruslike!
The Core War Standards '88
Proposed by
The International Core War Society
July 30, 1990
(Draft)
From the Redcode programmer's point of view, MARS is
composed of four primary units: a read/write memory (RAM),
a computing unit (ALU), two process cues (FIFO's), and the
control unit (CU). There are no registers visible to the
programmer; that is, memory is the only storage available
for both instructions and data.
RAM: All Redcode instructions occupy exactly one memory
location. Adressing in Redcode is relative, so it is best
to think of memory as being composed as a circular list; an
instructions that references memory adress zero is
referring to itself. Every RAM location is initialised to
the data pattern which corresponds to the instruction
'DAT 0 0' before loading any Core War Programs (elsewhere
referred to as "warriors").
FIFO: A game of Core War is played by pitting two Redcode
programs against eachother. Each attempts to force the
other to fail by causing it to execute a "halt"
instruction, (the DAT). During each machine cycle one
instruction from each program is executed, always in the
same order. It is thus necessary to maintain a program
counter for each side. This is the purpose of the process
queues. As will be seen, each side may consist of more than
one process. This is why a FIFO and not a single register
is necessary for each side. There are no upper or lower
limits to the size of the FIFO's, save the minimum of one
each, as battles cannot occur with less than two Core War
programs.
ALU: The computing unit performs all the arithmetic and
logical operations required by the Redcode instruction set,
and the Control Unit, such as adding two operands or
incrementing a program counter.
CU: As in any processor, the control unit has the
responsibility of fetching, decoding and executing
instructions. The control unit must also provide an
interface to the MARS supervisor function (ZEUS). The
supervisor may provide various support functions such as a
Redcode debugger, graphics display, parameter control,
etc., and is highly implementation specific.
Instruction Format:
A Redcode instruction has three fields: the opcode field
and two operand fields, denoted as A and B. the contents of
the opcode field specify the operation to be performed, and
the adressing modes to be used in evaluating the operands.
The operand fields may contain any number from zero to the
memory size minus one. Currently, eleven Redcode
instructions are defined. They are listed below, with a
mnemonic and a short description for each.
DAT A B : remove executing process from process queue
MOV A B : move A to B
ADD A B : add A to B
SUB A B : subtract A from B
JMP A B : jump to A
JMZ A B : jump to A if B is zero
JMN A B : jump to A if B is not zero
CMP A B : if A equals B then skip the next instruction
SLT A B : if A is less than B then skip next instruction
DJN A B : decrement B; if B is not zero then jump to A
SPL A B : place A in the process queue
Adressing Modes:
There are currently four adressing modes defined:
immediate, direct, indirect, and predecrement-indirect.
The default mode is direct. If no modifier symbol precedes
an operand, the value of the operand is used as an offset
from the memory location from which it was fetched. The
resulting memory location is the source and/or destination
of the data to be used by the instruction, or else is the
destination for branching instructions.
An octothorpe (#) is used to introduce an immediate
operand. The commemcial at sign (@) is used to introduce an
indirect operand. The value of the operand is used as an
offset, as it is with direct adressing. The B operand of
the resulting memory adress is then used as an offset from
the memory location from which it was fetched.
The less than sign (<) is used to introduce a predecrement
indirect operand. The action is the same as with @ with the
difference that the specified memory location is first
decremented and then afterwards used as a pointer.
All theory is grey, here are some REDCODE examples:
(Mostly 8000 or 8192 is used as Core size and 20000-30000
as instruction maximum)
; Warrior Gnom
l: MOV p @p
ADD #4 p
JMP l
p: DAT p
; Warrior KISS
l: MOV b1 <p
MOV b2 <p
JMN l p
MOV #-16 p
z: MOV k <p
JMN z p
MOV #-16 p
JMP l
b1: JMP -1
b2: SPL 0
k: DAT #0
p: DAT #-16
; Warrior PLAGUE
SPL k
SPL k
l: ADD #24 p
JMZ l @p
MOV b @p
MOV a <p
ADD #1 p
JMP l
DAT #1
DAT #2
DAT #3
DAT #4
p: DAT #5
k: MOV z <z
JMP k
z: DAT #-16
b: JMP -1
a: SPL 0
So far for now.
If someone is interested in more detailed information about
the 88 standards or some REDCODE programs I have collected feel
free to contact me.
MfG Stefan