Программа на SRL состоит из нескольких частей, которые можно перемешивать, как душе угодно
include header.inc ; вложить файл header.inc
const константа = значение ; константа
fix engine [0x10000] ; "обозвать" ячейку памяти именем
метка:
команды
еще_метка: ; комментарий
еще_команды
var переменная
var переменная = начальное_значение
data_label: ; чтобы обратиться к этим данным
data: 1, 2, 3, 4, 5, 6, 7 ; поместить в программу 7 чисел
data 10 ; поместить в программу 10 нулей
end
Программа разделяется на блоки автоматически (описание блоков см. в тексте "Процессы"). Но все же иногда полезно разбить один блок на несколько принудительно. Я точно не знаю, когда это может понадобиться, но команду такую я ввел:
---
Она принудительно разрежет блок на два. Но учтите, что два идущих подряд в исходнике блока, необязательно будут идти подряд в откомпилированном файле. То есть, применяйте разрыв блока, только если точно знаете, зачем это надо.
Теперь собственно инструкции. Я буду их писать в таком виде:
mov ident, exp
mov - это команда, ident - идентификатор или любое другое адресное выражение, exp - выражение.
Возможные типы ident:
| переменная | адрес переменной |
| метка | адрес метки |
| [exp] | адресное выражение |
| ident exp | любой другой адрес + выражение |
Возможные типы exp:
| число | 12345 (десятичное) или 0x12345 (16-ричное) |
| константа | объявление const |
| любая их комбинация | 5 + (some_const / 2) & 4 |
Например:
mov some_var - 10, 5 + (some_const & 4)
Приоритеты операций:
| ~ | унарный- | унарный+ |
| * | / | |
| + | - | |
| & | ||
| | |
| Инструкция | Комментарий |
| stop | см. Process - переход на run |
| reset | сброс процессора и переход на init |
| mov ident, exp | пересылка константа -> память |
| mov ident1, ident2 | пересылка память2 -> память1 |
| mov ident1, [ident2] | пересылка в память1 того, что лежит в памяти по адресу, записанного в ячейке память2 (в том числе допустимы выражения mov some_var, [[0x1000]]) |
| mov [ident1], ident2 | в другую сторону |
| mov ident1, @ident2 | записать в ident1 адрес ячейки ident2 |
| call ident | вызов подпрограммы |
| abort | переход на fail |
| nop | пустая команда |
| add ident, exp | сложение |
| add ident, ident | -//- |
| sub ident, exp | вычитание |
| sub ident, ident | -//- |
| mul ident, exp | умножение |
| mul ident, ident | -//- |
| div ident, exp | деление |
| div ident, ident | -//- |
| mod ident, exp | остаток от деления |
| mod ident, ident | -//- |
| inc ident | увеличить ident на 1 |
| dec ident | уменьшить на 1 |
| loop ident1, ident2 | уменьшить ident1, и если оно стало 0, то перейти на ident2 |
| xor ident, exp | исключающее или |
| xor ident, ident | -//- |
| and ident, exp | и |
| and ident, ident | -//- |
| or ident, exp | или |
| or ident, ident | -//- |
| ind ident | записать в ident то, что сейчас находится в ячейке по адресу ident |
| not ident | инвертировать все биты |
| clr ident | записать 0 в переменную |
| set ident | записать 1 во все биты переменной |
| cmp ident, exp | сравнить вычитанием |
| cmp ident, ident | -//- |
| test ident, exp | сравнить логическим умножением |
| test ident, ident | -//- |
| jmp ident | безусловный переход |
| ret | возврат из подпрограммы |
| jz ident | переход, если 0 |
| jnz ident | переход, если не 0 |
| jc ident | переход, если перенос |
| jnc ident | переход, если нет переноса |
| push ident | положить в стек переменную |
| push exp | положить в стек число |
| pop ident | вытащить из стека число и положить в переменную |
| pop exp | вытащить из стека exp чисел |
| jmp [ident] | косвенный переход |
| call [ident] | косвенный вызов подпрограммы |
| debug exp | вызвать debug-процедуру* с кодом exp |
| debug ident | вызвать debug-процедуру* с кодом ident |
* Сейчас debug-процедура при коде 0 извергает неприятный звук из звуковой платы.