|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Июл 18, 2004 13:09:34 [ Asterix: Я что-то не нахожу там, тот макрос($invoke) ] Там его и нет. Но есть проверка на затирание eax. Ищи по слову "overwritten" в ListView.mac. [ Asterix: А так я для себя уяснил, что нужно осторожно использовать eax при вложенных $invoke(), а также ADDR и всё будет нормально ;-) ] Ну конечно, если знаешь как они работают. ЗЫ: А вообще, я на дачу щас свалю :)) |
|
|
Дата: Июл 18, 2004 17:57:52 S_T_A_S_ Меня на flatassebler направили в топик где я нашёл такие макросы Privalov'а invk equ
macro invk proc,[arg]
{ common if ~ arg eq
reverse push arg
common end if
call near dword [proc+0] }
macro pushd [arg]
{ common if _#arg eq _invk arg
arg
push eax
else
push arg
end if }
Здесь мне не понятно: 1)invk equ ; что делает эта строка, присваивает пустое место? 2)common if ~ arg eq ; здесь что значит ~ и eq опять же с пустым местом. 3)common if _#arg eq _invk arg arg ; что значит эта строка? Вобщем чего мне не хватает в статьях про макросы это подробного разбора сложных макросов, с пояснением каждой строчки ;-) Я не могу пользоваться макросом пока полностью не пойму его суть. |
|
|
Дата: Июл 18, 2004 20:02:09 1) Верно. 2) common означает, что далее (до forward или reversе) все инструкции будут выполнены 1 раз. Далее идёт проверка того, что аргументы (arg) присутствуют, хотя бы один (значёк ~ отрицание) После директивы reversе (до forward или common) все инструкции будут выполнены по одной для каждого аргумента, переданного макросу после первого, начиная с последнего. Т.е. invk name,var1,var2 развернётся в следующее: push var2 push var1 call near dword [name+0] 3) arg - это имя аргумента, т.к. оно заключено в квадратные скобки, то таких аргументов может быть несколько. |
|
|
Дата: Июл 18, 2004 21:06:22Предположим, есть код: invk foo,0,1,2,3,4 Макрос invk развернётся в: ;common if ~ 0,1,2,3,4 eq ; ~ это отрицание, т.е. проверка, что список аргументов НЕ пуст ;reverse push 4 ; тогда помещаем их на стек push 3 push 2 push 1 push 0 ;common end if ; поскольку if находится в блоке common, то end if тоже должен быть в таком блоке call near dword [proc+0] ; это косвенный вызов, работает только для API ф-ций. Для своих нужно убрать скобочки Это упрощённый вариант invoke из MASM - без проверки количества аргумантов. Теперь такой код: push invk foo,0,1,2,3,4 ;common if _#arg eq _invk arg ; эта строка проверяет, начинается ли аргумент push с invk ; в нашем случае будет: if _invk foo,0,1,2,3,4 eq _invk foo,0,1,2,3,4 (если б не было "invk equ", то получилось бы: if _invk foo,0,1,2,3,4 eq _invk invk foo,0,1,2,3,4 - что не есть хорошо ) ; arg ; аргумент, как если б он был просто написан на отдельной строчке: invk foo,0,1,2,3,4 ; это в свою очередь будет заменено макросом выше push eax ; это понятно ; else ; эта ветка - для обычных аргументов - выполняется просто: push arg ; end if Теперь, если будет код: invoke bar, invk foo,0,1,2,3,4 то invoke начнёт делать push arg, как указано выше. Разные имена invoke и invk не совсем удобны, поскольку это в общем-то 2 одинаковых макроса, поэтому можно переименовать 2й в invoke. Т.е получится, что макрос объявлён 2 раза. Это необходимо обязательно делать, т.к. рекурсивно макросы в FASM не вызываются. Т.е. если макрос содержит внутри себя макрос с таким же именем, то вызывается макрос, который бал определёно ДО него. Если же макрос определён всего один раз, то будет сообщение об ошибке. |
|
|
Дата: Июл 19, 2004 04:24:49 · Поправил: Asterix pas S_T_A_S_ Спасибо, теперь кое-что начинает проясняться. Вот только здесь меня S_T_A_S_ опять запутал: Т.е получится, что макрос объявлён 2 раза. Это необходимо обязательно делать, т.к. рекурсивно макросы в FASM не вызываются. Т.е. если макрос содержит внутри себя макрос с таким же именем, то вызывается макрос, который бал определёно ДО него. Если же макрос определён всего один раз, то будет сообщение об ошибке. %) |
|
|
Дата: Июл 19, 2004 12:34:39 Asterix Из словаря компьютерной терминологии: Рекурсия: см. Рекурсия %) Но макросы в FASM рекурсию не поддерживают.
macro foo
{
foo
nop
}
foo <- illegal instruction
Когда FASM встречает вызов макроса foo, он соответственно, заменяет его содержимым этого макроса, т.е. foo.
Но что было foo до описания макроса foo? Это был неопределённый символ, поэтому и возникла ошибка.
Предположим, нужен макрос, который при своей работе вызывает себя повторно - т.е. рекурсивно.
Поскольку в FASM это невозможно, нужно идти другим путём -
просто определить макрос 2 раза.
macro foo
{
nop
}
macro foo
{
foo ; вызывается предыдущий макрос.
nop
}
foo <- Ok, получим 2 nop[code]
Теперь к invoke
В файле STDCALL.INC уже есть макрос:
[code]macro invoke proc,[arg] ; invoke procedure (indirect)
{ common
if ~ arg eq
reverse
pushd arg
common
call [proc]
else
call [proc]
end if }
Это точно такой же макрос, как и invk, приведённый выше. Зачем 2 одинаковых макроса с разными именами? Можно переименовать invk в invoke, и будет тогда работать код: invoke bar, <invoke foo,0,1,2,3,4> Т.е. как бы имитируется рекурсия :) |
|
|
Дата: Июл 19, 2004 13:08:49 S_T_A_S_ Спасибо, почти понятно, но можно чтоб не путаться, определить всё-таки второй макрос $invoke по аналогии с masm'ом и в таких случаях вызывать его, а в обычных - обычный invoke ? :-) А то боюсь можно накосячить ;-) |
|
|
Дата: Июл 19, 2004 16:11:30 Дык, можно, поменяй везде invk на $invoke и юзай так: invoke bar, <$invoke foo,0,1,2,3,4> Только смысл-то какой? |
|
|
Дата: Июл 19, 2004 16:27:43 S_T_A_S_ > Только смысл-то какой? Чтоб было видно что здесь поработал другой макрос, если будет косяк легче разобраться наверно ;-) Единственное что мне не нравиться это скобки <> |
|
|
Дата: Июл 19, 2004 16:55:55 В этом варианте скобочки можно вроде бы не писать - попробуй, а вообще, что бы не было косяков, нужно всякие проверки добавлять, я как раз щас этим и занимаюсь :) |
|
|
Дата: Июл 19, 2004 17:20:45 S_T_A_S_ Дык тяжело сразу эту логику проверок отшлифовать, она ведь тоже может глючить, я как смотрю на твои макросы то мне дурно делается, также как и от макросов Four-F %) |
|
|
Дата: Июл 19, 2004 18:22:15 Дык а мне как дурно делается %) Но делать-то надо :) |
|
|
Дата: Июл 21, 2004 01:58:10 · Поправил: Asterix |
|
|
Дата: Июл 21, 2004 15:20:54 Asterix Дык, я про такое и говорил - тупо для каждой ф-ции делать EQU.. Хотя для знатоков PERL нет сложностей перелопатить стандартные инклуды ;-) Но это только для API, а ведь есть ещё свои собственные PROC |
|
|
Дата: Июл 22, 2004 01:24:36 Asterix, мда... есть такое дело. Очень интересная ветка, но, IMHO, граничит с извратом. |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.122 |