Modesto
Умник
По многим просьбам, выкладываю первый на этом форуме туториал по директиве #emit
Данная директива предназначена для обращения к виртуальной машине (VM) посредством инструкций языка Assembler (ASM)
Данная директива предназначена для обращения к виртуальной машине (VM) посредством инструкций языка Assembler (ASM)
ВАЖНО!
Настоятельно НЕ РЕКОМЕНДУЮ использовать ассемблер при написании мода, так как в AMX он спроектирован для расширения возможностей, но никак не для написания ЭРПЭ модов.
Кроме 200к строк, убитых нервов, и забагованного кода (т.к стеком нужно манипулировать не только в границах пабликов) вы ничего не получите.
Кроме 200к строк, убитых нервов, и забагованного кода (т.к стеком нужно манипулировать не только в границах пабликов) вы ничего не получите.
I Введение
Как вы знаете, ассемблер - низкоуровневый язык, у него нет дата-контейнеров (где хранятся статичные данные - "глобальные переменные")
Всего для манипуляции присутствует 3 вида памяти (аккумуляторы)
PRI - "Primary" - основной аккумулятор, из него выводятся данные, используется для хранения результата
ALT - "Alternative" - альтернативный аккумулятор, обычно используется для хранения второстепенных данных (допустим, множитель числа)
STK - "Stack"/"Heap" - хранилище операндных данных, немного схож с ALT, но способен хранить в десятки раз больше
Всего для манипуляции присутствует 3 вида памяти (аккумуляторы)
PRI - "Primary" - основной аккумулятор, из него выводятся данные, используется для хранения результата
ALT - "Alternative" - альтернативный аккумулятор, обычно используется для хранения второстепенных данных (допустим, множитель числа)
STK - "Stack"/"Heap" - хранилище операндных данных, немного схож с ALT, но способен хранить в десятки раз больше
1.1 - Чтение из переменных
Основные типы загрузки данных в VM:Глобальные (можно использовать только глобальные переменные):
LOAD - загружает данные в СТЕК (STK) [ПРИМЕЧАНИЕ: эта инструкция работает как с локальными, так и с глобальными переменными]
LOAD.pri - загружает данные в PRI
LOAD.alt - загружает данные в ALT
LOAD.pri - загружает данные в PRI
LOAD.alt - загружает данные в ALT
Пример:
PHP:
new i = 11, d = 34, x = 62;
public OnGameModeInit()
{
#emit LOAD i // Теперь в стеке будет число 11
#emit LOAD.pri d // Теперь в PRI будет число 34
#emit LOAD.alt x // Теперь в ALT будет число 62
}
Локальные (собственно, можно использовать только локальные переменные):
LOAD.S - загружает данные в STK
LOAD.S.pri - загружает данные в PRI
LOAD.S.alt - загружает данные в ALT
Пример:LOAD.S.pri - загружает данные в PRI
LOAD.S.alt - загружает данные в ALT
PHP:
public OnGameModeInit()
{
new i = 16, d = 28, x = 71;
#emit LOAD.S i // Теперь в стеке будет число 16
#emit LOAD.S.pri d // Теперь в PRI будет число 28
#emit LOAD.S.alt x // Теперь в ALT будет число 71
}
PHP:
tock funct(oper1, Float:oper2, bool:oper3, oper4[], ...)
{
#emit LOAD.S.pri 12 // Мы загрузили в PRI аргумент под индексом 0 (oper1)
#emit LOAD.S.alt 16 // Мы загрузили в ALT аргумент под индексом 1 (Float:oper2)
#emit LOAD.S 20 // Мы загрузили в стек аргумент под индексом 2 (bool:oper3)
// Заметьте, что в стеке УЖЕ БЫЛИ данные (при вызове функции в стек записываются: адрес функции, кол-во аргументов, тип аргументов). предыдущей строкой мы создали коллизию стека, что делать не рекомендуется.
// Теперь в PRI находятся данные из аргумента oper1
1.2 - Константы
Запись статичных данных в VM осуществляется следующими инструкциями:CONST - загружает статичные данные в STK
CONST.pri - загружает статичные данные в PRI
CONST.alt - загружает статичные данные в ALT
Пример:
PHP:
public OnGameModeInit()
{
#emit CONST 17 // Теперь стек будет содержать число 17
#emit CONST.pri 21 // Теперь PRI будет содержать число 21
#emit CONST.alt 59 // Теперь ALT будет содержать число 59
}
1.3 - Запись в переменные
Читать данные из переменных мы научились. Теперь научимся их туда записывать.
Опять же, запись разделена на глобальную и локальную. НО, теперь это действительно так, если глобальными операндами можно было прочитать данные из локальных переменных, то записать уже будет нельзя.
Допустим, у нас в PRI хранится число 29, и нам нужно вывести его в переменную. Для этого прибегнем к операнду STOR
Глобальное чтение:
STOR - читает данные из стека, записывает в глобальную переменную
STOR.pri - читает данные из PRI, записывает в глобальную переменную
STOR.alt - читает данные из ALT, записывает в глобальную переменную
Пример:
PHP:
new dest, dest_, dest__;
public OnGameModeInit()
{
#emit STOR dest // Пишем в dest данные из стека
#emit STOR.pri dest_ // Пишем в dest_ данные из PRI
#emit STOR.alt dest__ // Пишем в dest__ данные из ALT
}
STOR.S - читает данные из стека, записывает в локальную переменную
STOR.S.pri - читает данные из PRI, записывает в локальную переменную
STOR.S.alt - читает данные из ALT, записывает в локальную переменную
Пример:
PHP:
public OnGameModeInit()
{
new dest, dest_, dest__;
#emit STOR.S dest // Пишем в dest данные из стека
#emit STOR.S.pri dest_ // Пишем в dest_ данные из PRI
#emit STOR.S.alt dest__ // Пишем в dest__ данные из ALT
}
Теперь вы наверное научились загружать и читать данные через #emit
Следующий урок coming soon
Следующий урок coming soon
Avtor:BJIADOKC
Последнее редактирование:
