RedCode
Материал из CoreWiki.
Описание языка RedCode
Содержание |
Нормативные документы
ICWS-86 (устарел и не используется)
Общие сведения
Формат ячейки - КОП А В , где КОП - это код операции А - первый операнд (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
хоть В-поле и не участвует в команде, всё равно выполнится пост-инкремент.
--YGREK 05:02, 22 Авг 2005 (EDT)

