· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.ASSEMBLER —› улучшение макроса

<< . 1 . 2 . 3 . >>

Посл.отвђт Сообщен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

Four-F
Кстати, вот function calls without using invoke (masm)


Дата: Июл 21, 2004 15:20:54

Asterix

Дык, я про такое и говорил - тупо для каждой ф-ции делать EQU..
Хотя для знатоков PERL нет сложностей перелопатить стандартные инклуды ;-)
Но это только для API, а ведь есть ещё свои собственные PROC


Дата: Июл 22, 2004 01:24:36

Asterix, мда... есть такое дело. Очень интересная ветка, но, IMHO, граничит с извратом.

<< . 1 . 2 . 3 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.122