RedCode

Материал из CoreWiki.

Перейти к: навигация, поиск

Описание языка RedCode

Содержание

Нормативные документы

ICWS-86 (устарел и не используется)

ICWS-88 (перевод)

ICWS-94 (перевод)

Общие сведения

Формат ячейки - КОП А В , где КОП - это код операции А - первый операнд (A-field) В - второй операнд (B-field)

Модификаторы команды хранятся вместе с кодом операции.

PC - Program Counter - указатель следующей команды для выполнения.


Команды

ADD Х, У
ADD
добавить к У значение Х и сохранить результат в У.
DAT
DATa
удалить вызывающий поток из списка потоков данной программы. Т.е. уничтожить поток. Операнды этой команды игнорируются, что между прочим отнюдь не запрещает хранить там данные. Если указан только один операнд, то он дублируется и для поля В.
MOV Х, У
MOVe
копировать ячейку Х в ячейку У.
SUB Х, У
SUBstract
вычесть из У значение Х и сохранить результат в У.
JMP Х
JuMP
переместить указатель PC на Х. Т.е. задать Х следующей командой для выполнения.
JMZ Х, У
JuMp if Zero
если значение У равно 0, то перейти на Х, иначе ничего не делать.
DJZ Х, У
Decrease and Jump if Zero
уменьшить значение У на единицу и если значение У стало равным 0, то переместить указатель PC на Х
CMP Х, У
CoMPare
сравнить значения Х и У и если они равны, то пропустить следующую команду, иначе ничего не делать.
JMN Х, У
JuMp if Not zero
если значение У равно 0, то ничего не делать, иначе задать Х как следующую команду для выполнения.
DJN Х, У
Decrease and Jump if Not zero
уменьшает значение У на единицу, если новое значение У не равно 0, перреместить PC на Х.
SPL Х
SPLit
создать новый поток, выполнение которого начинётся с адреса Х. Первая команда нового потока будет поставлена на выполнение после следующего перехода к текущему потоку, т.е. после выполнения команд всех остальных существующих потоков. Операнд У игнорируется.
SLT Х, У
Skip if Lower Than
сравнить значения Х и У, если Х < У, то пропустить следующую команду, иначе ничего не делать.
MUL Х, У
MULtiply
умножить У на значение Х и результат сохранить в Y.
DIV Х, У
DIVide
заменить У частным от деления его самого на значение Х. Если Х равно 0, то выполнивший команду поток уничтожается (ПОСЛЕ выполнения команды)
MOD Х, У
MODulus
заменить У остатком от деления его самого на значение Х. Если Х равно 0, то выполнивший команду поток уничтожается (ПОСЛЕ выполнения команды)
SEQ Х, У
Skip if EQual
то же самое что и cmp.
SNE Х, У
Skip if Not Equal
сравнить значения Х и У, если они не равны, то пропустить следующую команду, иначе ничего не делать.
NOP
No OPeration
ничего не делать.
LDP Х, У
LoaD P
копировать в У значение ячейки P-Space с индексом, задаваемым значением Х.
STP Х, У
STore P
копировать значение Х в ячейку P-Space с индексом, задаваемым значением У.


Режимы адресации

Всего есть три привычных вообщем-то режима : непосредственная, прямая и косвенная адресации.


Непосредственная указывается символом # перед операндом. В этом случае аргументом команды является само число. Например :

ADD #2, 10  ; добавить 2 к B-полю ячейки 10.
ADD #2, #10 ; добавить 2 к 10 и сохранить результат на месте 10 (в B-поле этой ячейки)


Прямая указывается символом $ или если никакого спец. символа перед операндом нету. При использовании прямой адресации в операции участвует содержимое ячейки по адресу, который указан в операнде. Например :

...
ADD $10, $-1  ; прибавить содержимое ячейки 10 (это 2) к ячейке -1 (то есть предыдущей)
...
10 : DAT 2

Эквивалентная запись :

...
ADD 10, -1 
...
10 : DAT 2


Косвенная (В-косвенная) указывается символом @. В операции используется значение расположенное по адресу, который храниться в В-поле ячейки, адрес которой указан в операнде. При чём все адреса отсчитываются от тех ячеек, где эти адреса расположены. То есть

...
ADD @10, -1 ; указываем на ячейку 10  <-----------------------------------|
...                                                                       | 
10 : DAT 0, 1  ; указываем на следующую ячейку (В поле)                   |
DAT 2 ; это (2) именно то число которое будет использоваться в операции ---

то есть в результате мы прибавим 2 к предыдущей ячейке.


Модификации косвенной адресации : постинкремент, предекремент, А-косвенная, А-постинкрементная, А-предекрементная.


Постинкрементная (префикс >) это то же самое, что косвенная но после выполнения команды, содержимое адресуемой ячейки увеличивается на 1.

Пример до выполнения команды add

add #10, >1
dat 0, 1
dat 0, 3

после выполнения команды add

add #10, >1
dat 0, 2  ; здесь инкремент пошёлся 
dat 0, 13 ; здесь 10 прибавилось

Очевидно, что эта адресация очень удобна для циклов.


Предекрементная (префикс <) уменьшает на одиничку содержимое адресуемой ячейки до выполнения команды.


A-косвенная (префикс *) отличается от В-косвенной тем, что используется А-поле адресуемой ячейки для получения окончательного адреса. Т.е.

ADD *10, -1 ; указываем на ячейку 10  <-----------------------------------|
...                                                                       | 
10 : DAT 1, 0  ; указываем на следующую ячейку (А поле)                   |
DAT 2 ; это (2) именно то число которое будет использоваться в операции ---

Соответственно и А-постинкрементная } и А-предекрементная { тоже используют А-поле адресуемой ячейки.

Метки

Высчитывать каждый раз относительные смещения при написании программы довольно утомительно, поэтому лучше использовать метки. Метка - идентификатор из алфавитно-цифровых символов, с первым символом - буквой или подчёркиванием. Записывается перед коммандой. Может оканчиваться двоеточием, которое не входит в имя метки.

Нотация Бекуса-Наура


Пример :

imp  mov imp, imp+1

или

imp:
   mov imp, imp+1

При использовании метки в инструкции, она заменяется на числовое значение, равное расстоянию от текущей ячейки до ячейки в которой метка была определена. Т.о. пример выше на самом деле означает

mov 0, 0+1

поскольку метка используется в той же ячейке где она и определена - то есть расстояние ноль.


Другой пример :

bomb  dat 0, 4
start mov bomb, @bomb
      add #4, bomb
      jmp start
      end start 

что еквивалентно

dat 0, 4
mov -1, @-1
add #4, -2
jmp -2
end -3

Использование end start означает что программа закончилась и начало её находится в ячейке start - end это не инструкция и не записывается в память, это директива - указание компилятору. Более новый синтаксис предписывает использовать для этих целей (обозначение начала программы) директиву org start перед телом программы.


Очевидно, что использование меток намного упрощает тяжёлые redcoderские будни :)

Модификаторы

Модификаторы определяют над какими частями операндов будет производиться действие. Записываются через точку после самой команды, например MOV.AB. После прекомпиляции MARS сам расставит модификаторы по умолчанию если они отсутствуют. Всего их 7, рассмотрим их действие на примере MOV :

MOV.A - перемещает А-поле источника в А-поле приёмника

MOV.B - перемещает В-поле источника в В-поле приёмника

MOV.AB - перемещает А-поле источника в В-поле приёмника

MOV.BA - перемещает В-поле источника в А-поле приёмника

MOV.F - перемещает оба поля источника в соответствующие поля приёмника

MOV.X - перемещает поля крест накрест (т.е. А в В и В в А)

MOV.I - перемещает всю ячейку источника в ячейку приёмника


Естественно модификаторы можно применять ко всем командам, но к некоторым командам они не будут иметь никакого смысла, например для JMP или SPL...

Примеры :

ADD.X 3, 5  ; прибавить содержимое поля А ячейки 3 к полю В ячейки 5
            ; также прибавить поле В ячейки  3 к полю А ячейки 5.
            ; Т.е. за один такт происходит две операции сложения.
ADD.F 3, 5  ; прибавляет поля ячейки 3 к полям ячейки 5. Т.е А к А и В к В.
ADD.I 3, 5  ; Эквивалентно .F, поскольку у кодов операций нет численного представления и
            ; их нельзя складывать
            ; (Помните - модификатор .I применяет комманду ко всей ячейке - КОП полеА полеВ
            ; а .F только к полям А и В )

А что происходит если модификатор не указан? В общем можно руководствоваться здравым смыслом, который впрочем реализован в стандарте '94 :

  • DAT NOP
    • Всегда .F но всё равно игнорируется.
  • MOV SEQ SNE CMP
    • Если адресация A-поля непосредственная, то .AB
    • Если у B-поля непосредственная а у A-поля нет, то .B
    • Если нет непосредственной адресации, то .I
  • ADD SUB MUL DIV MOD
    • Если A-поле с непосредственной адресацией, то .AB
    • Если B-поле непосредственное, а A-поле нет, то .B
    • Если нет непосредственной, то .F
  • SLT LDP STP
    • Если A-поле непосредственное, то .AB
    • Иначе, всегда .B
  • JMP JMZ JMN DJN SPL
    • Всегда .B (ничего не значит для JMP и SPL).


The beginners' guide to Redcode. The instruction modifiers

Замечания

  • Интересная особенность - следующая команда уничтожит ваш процесс
DAT 0, >100

но перед уничтожением всё равно выполнится инкремент В-поля ячейки 100.

Или аналогично

JMP 10, >200

хоть В-поле и не участвует в команде, всё равно выполнится пост-инкремент.




CoreWarLexicon

RedCodeFile


--YGREK 05:02, 22 Авг 2005 (EDT)

Личные инструменты