Добрый день. Люди, помогите с макросом. Никак не пойму их (макросов) философию Нужен макрос для вызова ф-ции не по имени (как в invoke), а по адресу в ячейке памяти. Примерно так: Код (Text): .data dwFuncAddr dd ? ;адрес ф-ции .code AddrInvoke dwFuncAddr, param1, param2, param3, ... Чтобы разворачивалось в push param3 push param2 push param1 call dwFuncAddr Заранее спасибо.
Вроде как для этого макрос не нужен, invoke сам должен справиться, если правильно прототип указать. Как-то так, но не уверен в правильности: Код (Text): .data dwFuncAddr:PTR PROTO :DWORD,:DWORD,:DWORD .code invoke dwFuncAddr 0, 1, 2 Своё макрос invoke на masm реализовать - изврат тот ещё
cresta А ты пользуй TASM и не знай горя: Код (Text): .model flat, stdcall ... funcs dd 1234 dup(?) ... call [funcs+eax*4], 1, 2, 3, 4
Три варианта: прямой, косвенный и вызов через регистр. Тебе нужен косвенный. Код (Text): .386 .model flat, stdcall option casemap:none ;::::::::::::::::::::::::::::::::::::::::::::::::: include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib ;::::::::::::::::::::::::::::::::::::::::::::::::: proto02 typedef proto :DWORD, :DWORD pproto02 typedef ptr proto02 ;::::::::::::::::::::::::::::::::::::::::::::::::: .data szCaption db "Caption", 0 szText db "Text", 0 pfnFunc dd offset Func ;::::::::::::::::::::::::::::::::::::::::::::::::: .code Func proc pText:LPSTR, pCaption:LPSTR invoke MessageBox, NULL, pText, pCaption, MB_OK ret Func endp start: invoke proto02 ptr [Func], addr szText, addr szCaption invoke pproto02 ptr [pfnFunc], addr szText, addr szCaption mov edx, pfnFunc assume edx:ptr proto02 invoke edx, addr szText, addr szCaption assume edx:nothing invoke ExitProcess, 0 end start
Это если количество параметров варьируется от 1 до 10, получается 20 typedef'ов, 10 Func'ов Похоже макрос тут не получится. В общем немного подумал, и сделал одну ф-цию (CDECL), может кому пригодится: Код (Text): AddrFunc PROTO C :DWORD, :VARARG .data? espVal dd ? espAddr dd ? .code AddrFunc proc C fnAddr:DWORD, params:VARARG option prologue : none option epilogue : none m2m espVal,[esp] mov espAddr,esp add esp,8 call dword ptr[esp-4] sub esp,8 mov esp,espAddr m2m [esp],espVal ret option prologue : prologuedef option epilogue : epiloguedef AddrFunc endp ;-------------------------------- ;вызов: invoke GetProcAddress, hModule, SADD("MessageBoxA") invoke AddrFunc, eax, 0, addr szMessage, addr szCaption, 0 Одна ф-ция и один proto для любого кол-ва параметров. И регистры не портит Возвращаемое значение как и положено, сидит в eax.
Так весь смысл invoke+proto в том и заключается, что проверяется кол-во параметров. Код (Text): proto00 TYPEDEF proto proto01 TYPEDEF proto :DWORD proto02 TYPEDEF proto :DWORD, :DWORD proto03 TYPEDEF proto :DWORD, :DWORD, :DWORD proto04 TYPEDEF proto :DWORD, :DWORD, :DWORD, :DWORD proto05 TYPEDEF proto :DWORD, :DWORD, :DWORD, :DWORD, :DWORD proto06 TYPEDEF proto :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD proto07 TYPEDEF proto :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD proto08 TYPEDEF proto :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD proto09 TYPEDEF proto :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD proto10 TYPEDEF proto :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD, :DWORD pproto00 TYPEDEF PTR proto00 pproto01 TYPEDEF PTR proto01 pproto02 TYPEDEF PTR proto02 pproto03 TYPEDEF PTR proto03 pproto04 TYPEDEF PTR proto04 pproto05 TYPEDEF PTR proto05 pproto06 TYPEDEF PTR proto06 pproto07 TYPEDEF PTR proto07 pproto08 TYPEDEF PTR proto08 pproto09 TYPEDEF PTR proto09 pproto10 TYPEDEF PTR proto10 Ну будет 20 typedef'ов - ну и что? А макрос тут просто не нужен. ЗЫ: Код (Text): invoke AddrFunc, <font color="red]eax</font><!--color-->, 0, addr szMessage, addr szCaption, 0 eax будет затёрт из-за addr
Если eax будет перетираться, масм выдаёт предупреждение: register overwritten by invoke и отказывается компилить код. В этом случае можно просто сделать invoke AddrFunc, dwMsgBoxAddr,... Если же компилит - значит eax не будет портиться. Собственно, я проверял на трех функциях: 3, 4 и 10 параметров (OpenSCManager, MessageBox и EnumServicesStatusEx). eax не портится (смотрел в Olly). Все вызовы проходят успешно.
Да, начёт "register overwritten by invoke" я забыл. А не затирается потому, что параметры глобальные - push offset. Если локальные переменные, то будет lea eax/push eax. Ну ладно - это ерунда. Я всё таки настаиваю на invoke+proto Вот так будет более благообразно: Код (Text): .386 .model flat, stdcall option casemap:none ;::::::::::::::::::::::::::::::::::::::::::::::::: include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib ;::::::::::::::::::::::::::::::::::::::::::::::::: proto04 typedef proto :DWORD, :DWORD, :DWORD, :DWORD pproto04 typedef ptr proto04 ;::::::::::::::::::::::::::::::::::::::::::::::::: .data? pfnMessageBoxA pproto04 ? ;::::::::::::::::::::::::::::::::::::::::::::::::: .data szCaption db "Caption", 0 szText db "Text", 0 szUser32 db "user32.dll", 0 szMessageBoxA db "MessageBoxA", 0 ;::::::::::::::::::::::::::::::::::::::::::::::::: .code start proc uses ebx invoke LoadLibrary, addr szUser32 mov ebx, eax invoke GetProcAddress, ebx, addr szMessageBoxA mov pfnMessageBoxA, eax invoke pfnMessageBoxA, NULL, addr szText, addr szCaption, MB_OK invoke FreeLibrary, ebx invoke ExitProcess, 0 start endp end start