PDA

Просмотр полной версии : [Function] GetNumberOfPublics - вычисляет количество public-функций



VVWVV
25.12.2016, 17:53
Описание:

Вычисляет количество public-функций в скрипте.

Параметры:

-

Возвращаемое значение:

Возвращает количество public-функций в скрипте.

Плюсы реализации:

При повторном вызове функция будет передовать кешированное значение.

Минусы реализации:
-

Код:


stock
GetNumberOfPublics()
{
static number_of_publics = -1;
if (number_of_publics < 0) {
new
pft,
addr;
#emit lctrl 1
#emit neg
#emit push.pri

#emit add.c 0x20
#emit stor.s.pri addr
#emit lref.s.pri addr
#emit load.s.alt addr
#emit add
#emit const.alt 0x20
#emit sub
#emit stor.s.pri pft

#emit pop.pri
#emit add.c 0x24
#emit stor.s.pri addr
#emit lref.s.pri addr
#emit load.s.alt addr
#emit add
#emit const.alt 0x24
#emit sub

#emit load.s.alt pft
#emit sub
#emit shr.c.pri 3
#emit stor.pri number_of_publics
}
return number_of_publics;
}


Пример использования:



forward public FirstPublicFunction();
public FirstPublicFunction()
{ }

forward public SecondPublicFunction();
public SecondPublicFunction()
{ }

main()
{
printf("Publics: %d", GetNumberOfPublics());
}

См. также:

[Function] Чистим массив игрока (http://pro-pawn.ru/showthread.php?7931)
[Function] Защита от DeAMX (new) (http://pro-pawn.ru/showthread.php?8277)
[Function] ClearKillFeed (http://pro-pawn.ru/showthread.php?12295)
[Function] dc_SleepFix (http://pro-pawn.ru/showthread.php?13188)
[Function] GetStackSize (http://pro-pawn.ru/showthread.php?10824)
[Function] itos (http://pro-pawn.ru/showthread.php?3243)
[Function] GetNumberOfArguments (http://pro-pawn.ru/showthread.php?14689)


Автор: VVWVV


Исключительно для pro-pawn.ru


Копирование данной статьи на других ресурсах без разрешения автора запрещено.

$continue$
25.12.2016, 19:42
А где можно применить?

VVWVV
25.12.2016, 20:04
А где можно применить?

Это можно применить, например, при переборе public-функций.

Daniel_Cortez
25.12.2016, 20:31
Откуда и каким образом происходит получение информации? По определению инструкции AMX способны читать данные только из секций данных и стека/кучи в скрипте.

VVWVV
25.12.2016, 20:33
Откуда и каким образом происходит получение информации? По определению инструкции AMX способны читать данные только из секций данных и стека/кучи в скрипте.

lref же.

Daniel_Cortez
25.12.2016, 20:35
lref же.
И что с того?

VVWVV
25.12.2016, 20:40
И что с того?

Данные AMX-инструкции не проверяют передаваемое значение в переменных. Кроме того, если сделать такую же конструкцию, но с load.i, то ВМ. будет ругаться на это.

Пельмень
25.12.2016, 20:53
Это уже есть тут, астанавись! (https://github.com/Zeex/amx_assembly/blob/master/amx_header.inc)

VVWVV
25.12.2016, 21:01
Это уже есть тут, астанавись! (https://github.com/Zeex/amx_assembly/blob/master/amx_header.inc)

Для использования функции из библиотеки нужна сама библиотека и функция. Вы ради одной функции будете качать всю библиотеку?

Хотя библиотека полезная. К тому же, наверное, стоит сделать обзор на неё (чем я сейчас и займусь).

Пельмень
25.12.2016, 21:08
Для использования функции из библиотеки нужна сама библиотека и функция. Вы ради одной функции будете качать всю библиотеку?

Хотя библиотека полезная. К тому же, наверное, стоит сделать обзор на неё (чем я сейчас и займусь).

Да, я просто не первый раз вижу, что ты что то делаешь а это уже есть в этой библиотеке, поэтому не смог не запостить

VVWVV
25.12.2016, 21:13
Да, я просто не первый раз вижу, что ты что то делаешь а это уже есть в этой библиотеке, поэтому не смог не запостить

Хм... Разве функция GetNumberOfArguments, точнее её аналог есть там?

Пельмень
25.12.2016, 21:15
Хм... Разве функция GetNumberOfArguments, точнее её аналог есть там?

GetNumPublics

VVWVV
25.12.2016, 21:16
GetNumPublics

Прочти внимательнее мой пост выше...

Пельмень
25.12.2016, 21:19
Прочти внимательнее мой пост выше...

Ну да, точно, нет, но есть numargs

VVWVV
25.12.2016, 21:19
Ну да, точно, нет, но есть numargs

Но ведь суть-то в том, что она быстрее numargs в любом случае.

Пельмень
25.12.2016, 21:22
Но ведь суть-то в том, что она быстрее numargs в любом случае.

Я просто не вижу смысла работать на скорость в 2017 году, эти миллисекунды ничего не дадут

VVWVV
25.12.2016, 21:30
Я просто не вижу смысла работать на скорость в 2017 году, эти миллисекунды ничего не дадут

Мне интересно, а когда ваш скрипт будет задыхаться от не оптимизированного кода, вы также будете говорить?

DeimoS
25.12.2016, 21:41
Я просто не вижу смысла работать на скорость в 2017 году, эти миллисекунды ничего не дадут

А в чём ты видишь смысл, если ни правильное распределение памяти, ни скорость обработки кода для тебя не являются важными?

Пельмень
25.12.2016, 21:46
Мне интересно, а когда ваш скрипт будет задыхаться от не оптимизированного кода, вы также будете говорить?

Он явно не будет задыхаться от неоптимизированного numargs) и сомневаюсь что вообще от чего то задохнется, где разница с "оптимзированным" вариантом для редкоиспользуемых функций будет доля миллисекунд

- - - Добавлено - - -


А в чём ты видишь смысл, если ни правильное распределение памяти, ни скорость обработки кода для тебя не являются важными?

Вижу смысл в удобстве написания кода, а не в парочке байт и доли миллисекунд выигрыша скорости при этом выписывая для этого какие то функции

VVWVV
25.12.2016, 21:48
Он явно не будет задыхаться от неоптимизированного numargs) и сомневаюсь что вообще от чего то задохнется, где разница с "оптимзированным" вариантом для редкоиспользуемых функций будет доля миллисекунд

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

Пельмень
25.12.2016, 21:51
Я построил вопрос абстрактно, не уточняя какие именно функции будут использоваться в вашем коде. Таким образом, вы ещё не ответили на мой вопрос.

Не волнуйся, если вдруг мне придется писать что то, и что конечно маловероятно писать мод, то он не задохнется от не оптимизированного кода

DeimoS
25.12.2016, 22:04
Он явно не будет задыхаться от неоптимизированного numargs) и сомневаюсь что вообще от чего то задохнется, где разница с "оптимзированным" вариантом для редкоиспользуемых функций будет доля миллисекунд

Он будет задыхаться от кучи других неоптимизированных функций, если уж совсем забить на оптимизацию. То же самое и с памятью: сегодня ты забил на подсчёт в одном месте, завтра в другом, послезавтра в третьем - и через неделю получил выход за пределы массива и скрипт в 100 строк, который компилируется по 3 минуты.


Вижу смысл в удобстве написания кода, а не в парочке байт и доли миллисекунд выигрыша скорости при этом выписывая для этого какие то функции

От того, что ты начнёшь использовать сторонние функции, а не нативные, удобства меньше не станет (ну разве что у тебя не синдром утёнка). И от того, что ты раз напишешь новую, более быструю функцию (подключишь плагин, повышающий скорость обработки кода/воспользуешься сторонней библиотекой и т.п.), ты так же ничего не потеряешь, а лишь приобретёшь.

И да, касаемо той же GetNumberOfArguments. Мне казалось, что адекватный человек понимает, что сию функцию есть смысл использовать только в местах, где частота вызова кода огромная и скорость его выполнения очень значима. И, как мне казалось, ни автор, ни кто либо ещё не предлагал повсеместно заменять numargs на эту функцию. Автор просто показал, что можно сделать быстрее, а уже понадобиться тебе эта функция или нет - никого, кроме тебя, это не волнует.
Хотя, судя по твоей упёртости, ты весь код пишешь под копирку, не думая о том, что где-то нужно больше уделить оптимизации памяти, а где-то - оптимизации скорости. А судя по одному из последних сообщений, дальше теории ты так и не уходил. Ну не суть.

Disinterpreter
25.12.2016, 22:15
И да, касаемо той же GetNumberOfArguments. Мне казалось, что адекватный человек понимает, что сию функцию есть смысл использовать только в местах, где частота вызова кода огромная и скорость его выполнения очень значима.

Я такой ужасный любитель интерпретируемых языков с утиной типизацией и любитель грамотного и красивого API-дизайна, скажите практическое применение функции?
Где её можно применить в гейммоде?

VVWVV
25.12.2016, 22:19
Я такой ужасный любитель интерпретируемых языков с утиной типизацией и любитель грамотного и красивого API-дизайна, скажите практическое применение функции?
Где её можно применить в гейммоде?

Например, при работе с #emit.

Disinterpreter
25.12.2016, 22:21
Например, при работе с #emit.

А конкретнее? Или получается вся эта функция бесполезна?

VVWVV
25.12.2016, 22:31
А конкретнее? Или получается вся эта функция бесполезна?

Если говорить конкретнее, то она чаще всего используется в цикле, который может содержать #emit.



for (new i = GetNumberOfPublics(); i != 0; --i)
{
// #emit код
}

Nexius_Tailer
25.12.2016, 22:34
Он будет задыхаться от кучи других неоптимизированных функций, если уж совсем забить на оптимизацию. То же самое и с памятью: сегодня ты забил на подсчёт в одном месте, завтра в другом, послезавтра в третьем - и через неделю получил выход за пределы массива и скрипт в 100 строк, который компилируется по 3 минуты.
Только использовать нативную функцию, но чуть медленней и целенаправленно писать говнокод - разные вещи. Реально игрок оценит лишь плохо работающий алгоритм по эффективности, а не микрооптимизации (хотя конечно, в каких-нибудь циклах или ещё каких-то слабых местах лучше и максимально стараться время выполнения сокращать). Так что это скорее крайности.

Daniel_Cortez
25.12.2016, 22:37
Ок, я на самом деле давно уже в курсе об уязвимости в lref.s.pri/alt (недавно зарепортил (https://github.com/compuphase/pawn/issues/26) её и ещё несколько других разработчику Pawn), просто хотел проверить знание теории.
Касаемо реализации, никогда не считал использование уязвимостей хорошим тоном - скорее, грязным хаком, коим это дело и является. Также остаётся под вопросом совместимость с JIT. Насколько помню, код инициализации в y_amx в сочетании с JIT вызывает краш как раз на моменте выполения инструкции lref.s.pri.
Кроме того, непонятно, в какой реальной ситуации может пригодиться такая функция - разве что в какой-нибудь библиотеке с кучей других хаков, наподобие y_amx, в которой реализован командный процессор и прочие поделия, которые по-хорошему следовало бы делать без всяких костылей в виде плагина.

VVWVV
25.12.2016, 22:41
Также остаётся под вопросом совместимость с JIT. Насколько помню, код инициализации в y_amx в сочетании с JIT вызывает краш как раз на моменте выполения инструкции lref.s.

Я не знаю что там в y_amx, но код компилируется отлично. А вот, например, динамический вызов реагирует с ним плохо:


#emit lctrl 6
#emit add.c 0x1C
#emit push.pri

#emit load.s.pri addr
#emit sctrl 6

Пельмень
25.12.2016, 22:42
Ок, я на самом деле давно уже в курсе об уязвимости в lref.s.pri/alt (недавно зарепортил (https://github.com/compuphase/pawn/issues/26) её и ещё несколько других разработчику Pawn), просто хотел проверить знание теории.
Касаемо реализации, никогда не считал использование уязвимостей хорошим тоном - скорее, грязным хаком, коим это дело и является. Также остаётся под вопросом совместимость с JIT. Насколько помню, код инициализации в y_amx в сочетании с JIT вызывает краш как раз на моменте выполения инструкции lref.s.pri.

Только вот amx_assembly не есть y_amx, хотя реализован он благодаря этой библиотеке, у юзлесса практически всё сделано на багах павн

Disinterpreter
25.12.2016, 23:51
Если говорить конкретнее, то она чаще всего используется в цикле, который может содержать #emit.



for (new i = GetNumberOfPublics(); i != 0; --i)
{
// #emit код
}


Я хочу услышать ГДЕ ЭТО ИСПОЛЬЗОВАТЬ?, а не как.

ziggi
26.12.2016, 00:14
Я хочу услышать ГДЕ ЭТО ИСПОЛЬЗОВАТЬ?, а не как.

Конкретно эту функцию можно применить для реализации других функций, связанных с public функциями (например, проверить индекс на выход за пределы, как здесь (https://github.com/Zeex/amx_assembly/blob/master/amx_header.inc#L346-L350)).

Лично я не вижу смысла конкретно в одной этой функции, есть же amx_assembly, набор функций которого понятно где и как можно применить. Да и список функций для "паблиокв" там внушительный: https://github.com/Zeex/amx_assembly/blob/master/amx_header.inc#L77-L84

Более того - эта функция, как мне кажется, реализована там гораздо более правильно: https://github.com/Zeex/amx_assembly/blob/master/amx_header.inc#L253-L256

VVWVV
26.12.2016, 00:33
Я хочу услышать ГДЕ ЭТО ИСПОЛЬЗОВАТЬ?, а не как.

DC уже ответил:



... разве что в какой-нибудь библиотеке с кучей других хаков, наподобие y_amx, в которой реализован командный процессор и прочие поделия, ...

Я же это использую в свои библиотеках, дабы не иметь зависимостей от других библиотек. Например, прогонять все public-функции для того, чтобы получить имя и т.п.



Лично я не вижу смысла конкретно в одной этой функции, есть же amx_assembly, набор функций которого понятно где и как можно применить. Да и список функций для "паблиокв" там внушительный: https://github.com/Zeex/amx_assembly/blob/master/amx_header.inc#L77-L84

Да, наверное.


Более того - эта функция, как мне кажется, реализована там гораздо более правильно: https://github.com/Zeex/amx_assembly/blob/master/amx_header.inc#L253-L256

Во-первых, она реализована без грязных приёмов.
Во-вторых, так как написано в Pawn Implementer Guide.

Disinterpreter
26.12.2016, 00:44
Окей спустя множество тем вы всё же ответили, спасибо.

DeimoS
26.12.2016, 05:29
Только использовать нативную функцию, но чуть медленней и целенаправленно писать говнокод - разные вещи. Реально игрок оценит лишь плохо работающий алгоритм по эффективности, а не микрооптимизации (хотя конечно, в каких-нибудь циклах или ещё каких-то слабых местах лучше и максимально стараться время выполнения сокращать). Так что это скорее крайности.

Но ведь именно про эти крайности я и говорил. Это как использование #emit в "/cc": можно, но реальной пользы мало :)
Только вот когда случится та самая ситуация, в которой понадобится подобная функция, ты сможешь просто зайти на форум и взять её, а не изобретать самостоятельно.

Daniel_Cortez
26.12.2016, 12:33
Только вот amx_assembly не есть y_amx
Тогда это (https://github.com/Misiur/YSI-Includes/blob/52224dafeee77ef630850916b49d7f820c89891e/YSI_Storage/y_amx.inc#L135) что?



Во-первых, она реализована без грязных приёмов.
Во-вторых, так как написано в Pawn Implementer Guide.
На уязвимостях виртуальной машины (AMX)... "Без грязных приёмов"...
Ок.