[Справочник] Байт-код SourcePawn

Kailo

Участник
Сообщения
168
Реакции
755
Для поиска нужной инструкции используйте поиск по странице (Ctrl+F).
Вы можете искать, как по имени инструкции, так и по значению в десятичной или HEX системах счисления.

Справочник имеет следующую структуру:
имя байт-кода параметры // Параметров может и не быть. Так же очень редко встречаются инструкции и переменном количеством параметров
значение (значение в HEX) // Значение в HEX дается для удобства использования и поиска
Мнемоническая расшифровка
Назначение инструкции.
PHP:
// Псевдо-код, выражающий действия инструкции.
Инструкции виртуальной машины Sourcepawn (Байт-код SP):
add
78 (4E)
addition
Суммирует значения основного и вспомогательного регистров, сохраняя результат в основной регистр.
PHP:
pri += alt;
add.c value
87 (57)
addition const
Прибавляет value к значению, хранящемуся в основном регистре, сохраняя результат в основной регистр.
PHP:
pri += value;
addr.alt offset
14 (0E)
addr.pri offset
13 (0D)
address alternative/primary
Сохраняет в соответствующий регистр адрес (в виртуальной памяти) локальной переменной.
PHP:
reg = frame + offset;
and
81 (51)
Производит побитовую конъюнкцию (битовое "И") между значениями основного и вспомогательного регистров, сохраняя результат в основной регистр
PHP:
pri &= alt;
bounds limit
121 (79)
Производит проверку значения из основного регистра. Если значение будет больше limit, вызывает ошибку выхода за пределы. Используется для проверки границ массивов во время исполнения программы.
PHP:
if (pri > limit)
    error("Out Of Bounds");
break
137 (89)
Инструкция для работы отладчика (debugger) программ написанных на SP.
Обычно располагаются в начале функций и в начале каждой строки кода в функции
(Если хоть раз работали с отладчиком, то знаете, что при остановки выполнения, обычно есть кнопка
"переход к следующей инструкции", для SP определение в какой момент надо остановиться,
делается как раз с помощью break).

call offset
49 (31)
Делает "вызов" функции расположенный по адресу offset, возвращаемое значение сохраняется в основной регистр. По окончанию вызова отчищает стек от параметров вызова. Кол-во параметров должно было быть передано на вершине стека после параметров.
Если описывать процесс вызова более подробно:
Проверяет корректность адреса и наличие функции по нему.
Помещает на вершину стека адрес старого фрейма и за ним константу 0.
Меняет значение текущего фрейма окружения и запускает цикл чтения инструкций по адресу, до тех пор пока не будет совершен возврат.
По окончанию вызова вытаскивает с вершины 0, а затем адрес фрейма до вызова и устанавливает его как значение текущего фрейма.
Получает с вершины стека значение, которое обозначает кол-во параметров при вызове и извлекает из стека эти параметры.
Сохраняет значение полученное при вызове в основной регистр.

casetbl params...
130 (82)
case table
Описывает структуру switch конструкции.
Код:
casetbl <case num> <default> <case1 int> <case1 adr> <case2 int> <case2 adr> ... <caseN int> <caseN adr>
Первый параметр инструкции говорит о том сколько "case-ов" в конструкции.
Второй параметр это адрес где находится "default case". Если его нет, то адрес указывает на следующую инструкцию после конца switch конструкции, она обычно следует как раз после casetbl инструкции.
Далее идет парами [число обозначающие case, адрес где находится код case] такое кол-во пар, как указано в 1-ом параметре.

const address value
156 (9С)
constant
Устанавливает значение по адресу памяти. Используется для присваивания значений глобальным переменным.
PHP:
memory[address] = value;
const.alt value
12 (0С)
const.pri value
11 (0B)
constant alternative/primary
Устанавливает значение соответствующему регистру.
PHP:
reg = value;
const.s offset value
157 (9D)
constant stack
Устанавливает значение локальной переменной.
PHP:
memory[frame + offset] = value;
dec address
114 (72)
decrement
Производит декремент значения, хранящегося по адресу address.
PHP:
memory[address] -= 1;
dec.alt
113 (71)
dec.pri
112 (70)
decrement alternative/primary
Производит декремент значения, хранящегося в соответствующем регистре.
PHP:
reg -= 1;
dec.i
116 (74)
decrement ? (сам не знаю)
Производит декремент значения, хранящегося по адресу взятого из основного регистра. Используется для декремента значений массивов. Сначала вычисляется адрес нужной ячейки и сохраняется в основном регистре, потом вызывается эта инструкция.
PHP:
addr = pri;
if (CheckIfBadAddr(addr))
    error("Bad Address");
memory[addr] -= 1;
dec.s offset
115 (73)
decrement stack
Производит декремент значения локальной переменной.
PHP:
memory[frame + offset] -= 1;
endproc
166 (A6)
end procedure
Является индикатором конца функции.
В настоящий момент не генерируется компилятором.

eq
95 (5F)
equal
Производит сравнение значений содержащихся в основном и вспомогательном регистрах, если значения равны, то устанавливает значение 1, иначе 0, для основного регистра.
PHP:
pri = (pri == alt) ? 1 : 0;
eq.c.alt value
106 (6A)
eq.c.pri value
105 (69)
equal const alternative/primary
Производит сравнение значения из соответствующего регистра с переданным значением, если значения равны, то устанавливает значение 1, иначе 0, для основного регистра.
PHP:
pri = (reg == value) ? 1 : 0;
fill amount
119 (77)
Значение хранящиеся в вспомогательном регистре интерпретируется как адрес памяти, с которого надо запомнить amount байтов. Байты преобразуются в кол-во ячеек для заполнения, в которые заносится значение хранящиеся в основном регистре. Перед заполнение адрес проверяется. Используется для инициализации локальных массивов.
PHP:
if (!CheckMemoryBounds(alt, amount))
    error();
for (i = 0; i < (amount / cellsize); i++)
    memory[alt + i * cellsize] = pri;
genarray dims
162 (A2)
genarray.z dims
163 (A3)
generate array (zero)
Генерирует динамический массив в heap разделе памяти, размерность массива передается как dims, а размеры размерностей передаются ранее в стеке, после чего от туда извлекаются при генерации нового массива. После конца генерации адрес массива помещается на вершину стека, тем самым формируя локальную переменную. zero версия имеет заполнение массива нулями после генерации.

halt value
120 (78)
Неиспользуемый код, который предположительно должен прерывать (или ставить на ожидание) работу плагина. Исполнение этого кода приведет к ошибке. Может быть сгенерирован конструкцией "sleep". Так же присутствует в начале каждой ".code" секции, как заглушка для "main" функции (которая так же никогда не вызывается).

heap amount
45 (2D)
Выделяет amount байт (думаю должно быть кратно 4) в куче, занося адрес во вспомогательный регистр.
PHP:
alt = heapAlloc(amount)
idxaddr
27 (1B)
index address
Берет адрес из вспомогательного регистра и прибавляет к нему значение из основного регистра умноженное на размер ячейки. Используется для одномерных массивов, для получение адреса со смещением. К примеру, у нас численный массив расположенный по адресу 600, и нам надо узнать адрес ячейки с индексом 5: 600 + 5 * 4 = 620.
PHP:
pri = alt + pri * cellsize;
inc address
109 (6D)
increment
Производит инкремент значения, хранящегося по адресу address.
PHP:
memory[address] += 1;
inc.alt
108 (6C)
inc.pri
107 (6B)
increment alternative/primary
Производит инкремент значения, хранящегося в соответствующем регистре.
PHP:
reg += 1;
inc.i
111 (6F)
increment ?
Производит инкремент значения, хранящегося по адресу взятого из основного регистра. Используется для инкремента значений массивов. Сначала вычисляется адрес нужной ячейки и сохраняется в основном регистре, потом вызывается эта инструкция.
PHP:
addr = pri;
if (CheckIfBadAddr(addr))
    error("Bad Address");
memory[addr] += 1;
inc.s offset
110 (6E)
increment stack
Производит инкремент значения локальной переменной.
PHP:
memory[frame + offset] += 1;
invert
86 (56)
Производит операцию "побитового отрицания (НЕ)" над значением хранящемся в основном регистре.
PHP:
pri = ~pri;
jeq address
55 (37)
jump equal
Условный переход по адресу address при условии равенства содержимого основного и вспомогательного регистров. Т.е. следующий будет выполнена не инструкция, следующая за текущий, а находящаяся по адресу address.
PHP:
if (pri == alt)
   goto point;
...
point:
...
jneq address
56 (38)
jump not equal
Условный переход по адресу address при условии не равенства содержимого основного и вспомогательного регистров.
PHP:
if (pri != alt)
   goto point;
...
point:
...
jnz address
54 (36)
jump not zero
Условный переход по адресу address если содержимое основного регистра не равно 0.
PHP:
if (pri != 0)
   goto point;
...
point:
...
jsgeq address
64 (40)
jump signed greater equal
Условный переход по адресу address при условии, что значение основного регистра больше или равно значению вспомогательного регистра.
PHP:
if (pri >= alt)
   goto point;
...
point:
...
jsgrtr address
63 (3F)
jump signed greater
Условный переход по адресу address при условии, что значение основного регистра больше значения вспомогательного регистра.
PHP:
if (pri > alt)
   goto point;
...
point:
...
jsleq address
62 (3E)
jump signed less equal
Условный переход по адресу address при условии, что значение основного регистра меньше или равно значению вспомогательного регистра.
PHP:
if (pri <= alt)
   goto point;
...
point:
...
jsless address
61 (3D)
jump signed less
Условный переход по адресу address при условии, что значение основного регистра меньше значения вспомогательного регистра.
PHP:
if (pri < alt)
   goto point;
...
point:
...
jump address
51 (33)
jump
Безусловный переход по указанному адресу. Т.е. следующий будет выполнена не инструкция, следующая за текущий, а находящаяся по адресу address.
PHP:
goto point;
...
point:
...
jzer address
53 (35)
jump zero
Условный переход по адресу address если содержимое основного регистра равно 0.
PHP:
if (pri == 0)
   goto point;
...
point:
...
lidx
25 (19)
load index
Берет адрес из вспомогательного регистра и прибавляет к нему значение из основного регистра умноженное на размер ячейки (аналогично idxaddr), после чего получает значение хранимое по данному адресу и помещает его в основной регистр.
PHP:
pri = memory[alt + pri * cellsize];
load.pri address
1 (01)
load.alt address
2 (02)
load primary/alternative
Получает значение хранимое по адресу address сохраняя в соответствующий регистр.
PHP:
reg = memory[address];
load.both address1 address2
154 (9A)
Получает значения хранимые по адресам address1 и address2 сохраняя их в регистры.
PHP:
pri = memory[address1];
alt = memory[address2];
load.i
9 (09)
load ?
Получает значение хранимое по адресу находящемся в основном регистре куда и сохраняет полученное значение.
PHP:
pri = memory[pri];
load.s.pri offset
3 (03)
load.s.alt offset
4 (04)
load stack primary/alternative
Получает значение хранимое в локальной переменной или аргументе сохраняя в соответствующий регистр.
PHP:
reg = memory[frame + offset];
load.s.both offset1 offset2
155 (9B)
load stack both
Получает значение хранимое в локальных переменных или аргументах сохраняя в соответствующий регистр.
PHP:
pri = memory[frame + offset1];
alt = memory[frame + offset2];
lodb.i width
10 (0A)
load byte ?
Получает значение размером width байт хранимое по адресу находящемся в основном регистре куда и сохраняет полученное значение.
PHP:
pri = memory[pri];
switch (width)
{
case 1: pri &= 0xFF;
case 2: pri &= 0xFFFF;
case 4: // do nothing
default: error();
}
lref.s.pri offset
7 (07)
lref.s.alt offset
8 (08)
load reference stack primary/alternative
Получает значение хранимое по адресу указному в аргументе (используется для получения значений аргументов ссылок "int &arg") сохраняя в соответствующий регистр.
PHP:
reg = memory[memory[frame + offset]];
move.pri
33 (21)
move primary
Устанавливает значение основного регистра равным значению вспомогательного.
PHP:
pri = alt
move.alt
34 (22)
move alternative
Устанавливает значение вспомогательного регистра равным значению основного.
PHP:
alt = pri
movs amount
117 (75)
Копирует amount байт с адреса полученного из основного регистра по адресу указанному в вспомогательном регистре. Количество amount кратно 4.
PHP:
memmove(alt, pri, amount);
neg
85 (55)
negative
Меняет знак числа содержащегося в основном регистре.
PHP:
pri = -pri;
neq
96 (60)
not equal
Сравнивает (не равенство) значения основного и вспомогательного регистров, помещая результат сравнения в основной регистр.
PHP:
pri = pri != alt;
not
84 (54)
Применяет логическое отрицание к содержимому основного регистра сохраняя результат там же.
PHP:
pri = pri ? 0 : 1;
or
82 (52)
Производит побитовую дизъюнкцию (битовое "ИЛИ") между значениями основного и вспомогательного регистров, сохраняя результат в основной регистр.
PHP:
pri = pri | alt;
pop.pri
42 (2A)
pop.alt
43 (2B)
pop primary/alternative
Получает значение с вершины стек помещая его в указанный регистр.
PHP:
reg = stack.pop();
proc
46 (2E)
procedure
Обозначает начало фукнции. В виртуальной машине вызывает инициализацию значений перед выполнением функции.

push.pri
36 (26)
push.alt
37 (25)
Помещает значение из указанного регистра на вершину стека.
PHP:
stack.push(reg);
push address
40 (28)
push2 address1 address2
139 (8B)
push3 address1 address2 address3
143 (8F)
push4 address1 address2 address3 address4
147 (93)
push5 address1 address2 address3 address4 address5
151 (97)
Получает значение с указанного адреса после чего помещает его на вершину стека.
pushN нужны для оптимизации и эквивалентны вызову push N раз.
PHP:
stack.push(memory[address1]);
stack.push(memory[address2]);
...
stack.push(memory[addressN]);
push.adr offset
133 (85)
push2.adr offset1 offset2
141 (8D)
push3.adr offset1 offset2 offset3
145 (91)
push4.adr offset1 offset2 offset3 offset4
149 (95)
push5.adr offset1 offset2 offset3 offset4 offset5
153 (99)
push address
Получает адрес локальной переменной/аргумента после чего помещает его на вершину стека.
pushN.adr нужны для оптимизации и эквивалентны вызову push.adr N раз.
PHP:
stack.push(frame + offset1);
stack.push(frame + offset2);
...
stack.push(frame + offsetN);
push.c value
39 (27)
push2.c value1 value2
138 (8A)
push3.c value1 value2 value3
142 (8E)
push4.c value1 value2 value3 value4
146 (92)
push5.c value1 value2 value3 value4 value5
150 (96)
push const
Помещает константное значение на вершину стека.
Таким образом передаются или константы или адреса глобальных переменных/массивов.
PHP:
stack.push(value1);
stack.push(value2);
...
stack.push(valueN);
push.s offset
41 (29)
push2.s offset1 offset2
140 (8C)
push3.s offset1 offset2 offset3
144 (90)
push4.s offset1 offset2 offset3 offset4
148 (94)
push5.s offset1 offset2 offset3 offset4 offset5
152 (98)
push stack
Помещает значение локальной переменной/аргумента на вершину стека.
PHP:
stack.push(memory[frame + offset1]);
stack.push(memory[frame + offset2]);
...
stack.push(memory[frame + offsetN]);
retn
48 (30)
return
Заканчивает исполнение функции. Возвращаемое функцией значение должно быть задано до вызова retn в основном регистре.

sdiv.alt
74 (4A)
signed divison alternative
Производит целочисленное деление (с учетом знаков переменных) значения из основного регистра на значение из вспомогательного, сохраняя кол-во целых в основном регистре, а остаток от деления в вспомогательном.
PHP:
dividend = pir; // делимое
divisor = alt; // делитель
pri = dividend / divisor;
alt = dividend % divisor;
sless
101 (65)
signed less
Производит сравнение (меньше) между значениями основного и вспомогательного регистров помещая результат в основной регистр.
PHP:
pri = pri < alt;
sleq
102 (66)
signed less equal
Производит сравнение (меньше или равно) между значениями основного и вспомогательного регистров помещая результат в основной регистр.
PHP:
pri = pri <= alt;
sgrtr
103 (67)
signed greater
Производит сравнение (больше) между значениями основного и вспомогательного регистров помещая результат в основной регистр.
PHP:
pri = pri > alt;
sgeq
104 (68)
signed greater equal
Производит сравнение (больше или равно) между значениями основного и вспомогательного регистров помещая результат в основной регистр.
PHP:
pri = pri >= alt;
shl
65 (41)
shift left
Производит битовый сдвиг значения из основного регистра влево на кол-во шагов равное значению в вспомогательном регистре. Сохраняет результат в основном регистре.
PHP:
pri = pri << alt;
shl.c.pri amount
68 (44)
shl.c.alt amount
69 (45)
shift const primary/alternative
Производит битовый сдвиг значения из указанного регистра влево на кол-во шагов равное amount. Сохраняет результат в том же регистре.
PHP:
reg = reg << amount;
shr
66 (42)
shift right
Производит битовый арифметический сдвиг значения из указанного регистра вправо на кол-во шагов равное значению в вспомогательном регистре. Сохраняет результат в основном регистре.
PHP:
pri = pri >> alt;
sshr
67 (43)
signed shift right
Производит битовый логический сдвиг значения из указанного регистра вправо на кол-во шагов равное значению в вспомогательном регистре. Сохраняет результат в основном регистре.
PHP:
pri = pri >>> alt;
(Подробнее о битовых сдвигах и разнице между арифметическим и логическим см. Википедия:Битовый сдвиг)

smul
72 (48)
signed multiplication
Производит умножение значений из основного и вспомогательного регистров, сохраняя результат в основном регистре.
PHP:
pri = pri * alt;
smul.c value
88 (58)
signed multiplication const
Производит умножение значения из основного регистра и константы value, сохраняя результат в основном регистре.
PHP:
pri = pri * value;
sref.s.pri offset
21 (15)
sref.s.alt offset
22 (16)
store reference stack primary/alternative
Сохраняет значение из указанного регистра по адресу указанному в аргументе (используется для аргументов ссылок (int &arg).
PHP:
memory[memory[frame + offset]] = reg;
stack value
44 (2C)
Изменяет значение указателя вершины стека. Используется для выделения/освобождения памяти локальным переменным хранимым в стеке. Отрицательные значения - выделение, положительные - освобождение (это связанно с тем что стек перевернут в памяти, что вам известно из прошлого урока).
PHP:
sp += value; // sp = stack pointer (указатель (вершины) стека)
stor.pri address
15 (0F)
stor.alt address
16 (10)
store primary/alternative
Сохраняет значение из указного регистра по адресу address. Используется для установки значения глобальным переменным.
PHP:
memory[address] = reg;
stor.i
23 (17)
store ?
Сохраняет значение из основного регистра по адресу указанному в вспомогательном регистре. Используется для установки значения ячейкам массивов.
PHP:
memory[alt] = pri;
stor.s.pri offset
17 (11)
stor.s.alt offset
18 (12)
store stack primary/alternative
Сохраняет значение из указного регистра в локальную переменную/аргумент.
PHP:
memory[frame + offset] = reg;
strb.i width
24 (18)
store byte ?
Сохраняет значение размером width байт из основного регистра по адресу указанному в вспомогательном регистре. Используется для установки значения ячейкам буквенных массивов.
PHP:
switch (width)
{
case 1: view_as<char>(memory[alt]) = view_as<char>(pri) ;
case 2: view_as<WORD>(memory[alt]) = view_as<WORD>(pri); // WORD - тип данных размер переменной которого 16 бит = 2 байта.
case 4: memory[alt] = pri;
default: error();
}
stradjust.pri
164 (A4)
Получает кол-во ячеек необходимых, чтобы вместить кол-во байт указанное в основном регистре. Результат сохраняется там же. Нужно для динамических буквенных массивов (genarray) т.к. там размер указывается в ячейках.
PHP:
pri = (pri + 4) / 4;
sub
79 (4F)
subtraction
Производит вычитание из значения основного регистра значения вспомогательного регистра. Результат сохраняется в основной регистр.
PHP:
pri = pri - alt;
sub.alt
80 (50)
subtraction
Производит вычитание из значения вспомогательного регистра значения основного регистра. Результат сохраняется в основной регистр.
PHP:
pri = alt - pri;
// Нет инструкции вычитания константы, вместо этого используется прибавление отрицательного константного значения.

swap.pri
131 (83)
swap.alt
132 (84)
swap primary/alternative
Производит обмен значениями между указанным регистром и значением находящемся на вершине стека.
PHP:
tmp = stack.pop();
stack.push(reg);
reg = tmp;
switch address
129 (81)
Инструкция обозначающая начало switch конструкции. Адрес address должен указывать на casetbl инструкцию располагающуюся в конце switch конструкции.

sysreq.n index nparams
135 (87)
Производит вызов Native функции. Индекс index соответствует номеру функции в .native разделе smx. Параметр nparams сообщает кол-во аргументов при вызове функции, которые будут отчищены из стека по завершению вызова. Возвращаемое заначение при вызове помещается в основной регистр.

tracker.pop.setheap
161 (A1)
Вызывается для для уничтожения динамического массива. Созданная инструкцией genarray локальная перемененная/ссылка должная находиться на вершине стека. Размер стека остается неизменным при этом выполнении этой инструкции.

tracker.push.c
160 (A0)
// В реальности не встречал

xchg
35 (23)
exchange
Производит обмен значениями между регистрами.
PHP:
tmp = pri;
pri = alt;
alt = tmp;
xor
83 (53)
exclusive or
Производит битовую операцию "Исключительное ИЛИ" над значениями из основного и вспомогательного регистров. Результат сохраняется в основном регистре.
PHP:
pri = pri ^ alt;
(Название не просто так придумано и напоминает о том как оно работает. Т.е. работает как ИЛИ но с учетом исключения, эксклюзивности результата. Т.е. при случае когда оба значения равны 1 - результат 0.)

zero address
91 (5B)
Присваивает нулевое значение по адресу address.
PHP:
memory[address] = 0;
zero.pri
89 (59)
zero.alt
90 (5A)
zero primary/alternative
Присваивает нулевое значение указанному регистру.
PHP:
reg = 0;
zero.s offset
92 (5C)
zero stack
Присваивает нулевое значение локальной переменной/аргументу.
PHP:
memory[frame + offset] = 0;
Не генерируемые компилятором и устаревшие инструкции:

sysreq.c

? (?)
// TODO

idxaddr.b

28 (1C)

ldgfn.pri
167 (A7)

lidx.b
26 (1A)

nop
134 (86)

shr.c.alt
71 (47)
// Устаревшая

shr.c.pri
70 (46)
// Устаревшая

Больше не генерируемых инструкций можно найти здесь:
[email protected]/sourcepawn: include/smx/smx-v1-opcodes.hsmx-v1-opcodes.h
(Смотрите инструкции начинающиеся с "_U" (_G - генерируемые, _U - не генерируемые)
 
Последнее редактирование:
Сверху