У меня вопрос: с недавнего времени стал использовать процедуры в программировании. Выносил некоторые функции в процедуры и все было впорядке. Процедуры использовал вида: конструкция1 Code (Text): proc subfunction1,param1,param2 pushad ;сохраняемсо ....... ;тело ....... ;функции popad ;восстанавливаемсо mov esi,[param1] ; сохраняем первый возвращаемый функцией параметр mov edi,[param2] ; сохраняем первый возвращаемый функцией параметр ret ;возврат обратно endp или второй вариант(с глобальными переменными): Code (Text): proc subfunction1,param1,param2 pushad ;сохраняемсо ....... ;тело ....... ;функции popad ;восстанавливаемсо mov [global1],esi ; сохраняем в глобальную переменную mov [global2],edi ; сохраняем в глобальную переменную ret ;возврат обратно endp При таком виде процедура не создает кадра стека т.е как я только что написал код - так и будет в листинге. Проблема возникла в случае, когда функция не такая уже и маленькая и без локальных переменных в ней не обойдешься. Сама процедура имеет вид: Code (Text): proc function locals some_variable1 dd ? some_variable2 dd ? some_variable3 dd ? endl .......................... .......................... .......................... ret endp фасм генерирует функцию такого вида: Code (Text): PUSH EBP MOV EBP,ESP SUB ESP,4 ......................... ......................... ......................... [b]leave [/b] ret т.е формирует кадр стека. При таком раскладе получается невозможна конструкция с передачей переменных обратно функции(конструкция1), которая вызывала подфункцию т.е при выходе очищается кадр стека. В общем-то сам вопрос: как можно в процедуре, в которой используются (locals endl) локальные переменные передать обратно вызывающей функции значения, при этом НЕиспользуя глобальные переменные ?
Code (Text): sub esp,lalala stdcall p1,1,2,3,esp proc p1 param1, param2, param3, pVars ... mov eax,[pVars] mov [eax],ebx mov [eax+4],ecx mov [eax],edx ... или pop dword[eax] pop dword[eax+4] ... или чего в голово придет endp
common_up Если я правильно понял вопрос, то в варианте "конструкция 1" должно быть: mov [param1],esi ; сохраняем первый возвращаемый функцией параметр mov [param2],edi ; сохраняем первый возвращаемый функцией параметр , а не наоборот. Подобный способ возврата результатов из функции не принят. Более распространённым является вариант, предложенный iZzz32. Тем не менее, если хотите "остаться при своём", просто используйте в своих функциях cdecl, но вызывайте их, как stdcall. Тогда все переданные параметры будут оставаться в стеке: Code (Text): ;вызов cdecl-функции с двумя параметрами, как stdcall: stdcall subfunction1,eax,ecx pop ecx ;\ pop eax ;_> выборка результатов из стека ;cdecl-функция с двумя параметрами: proc subfunction1 c,param1,param2 ;pushad ;здесь логичнее было бы использовать ;....... ;uses eax ebx ;....... ;и т.д. в заголовке функции, указывая сохранять только необходимое. ;popad ;pushad/popad — плохой стиль mov [param1], esi ; сохраняем первый возвращаемый функцией параметр mov [param2], edi ; сохраняем первый возвращаемый функцией параметр ret ;возврат обратно endp
вот как на самом деле: Code (Text): proc ff locals variable dd ? endl mov eax,0x10 mov [variable],eax stdcall ww,[variable],[variable],[variable],[variable] mov eax,[variable] int 3 mov ebx,[esp-0x1C] mov eax,[esp-0x10] endp proc ww,waaa,waaa1,waaa2,waaa3 locals variable dd ? variable1 dd ? variable2 dd ? variable3 dd ? variable4 dd ? endl mov [variable],0x1 mov [variable1],0x2 mov [variable2],0x3 mov [variable3],0x4 mov [waaa],0x5 mov [waaa1],0x6 mov [waaa2],0x7 mov [waaa3],0x8 ret так что можно использовать в локальных переменных subfunction локальные OUTPUT_variables(так и сами локальные переменные, зарезервированные под использование самой сабфункцией), так и сами параметры функции, только при использовании параметров функции возникает проблема: если количество возвращаемых значений больше, чем количество параметров принимаемых сабфункцией - то облом, хотя можно это обойти, вызавая сабфункцию с нужными параметрами+несколько фейковых параметров, чтобы можно было вернуть необходимое кол-во параметров В общем полная свобода. дополнение: при вызове сабфункции с одним параметром значение последней локальной переменной = esp-0x10, при увеличении параметров функции добавляем к 10+4