fasm+процедуры

Тема в разделе "WASM.BEGINNERS", создана пользователем common_up, 27 авг 2010.

  1. common_up

    common_up New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2010
    Сообщения:
    85
    У меня вопрос:
    с недавнего времени стал использовать процедуры в программировании. Выносил некоторые функции в процедуры и все было впорядке.
    Процедуры использовал вида:

    конструкция1
    Код (Text):
    1. proc subfunction1,param1,param2
    2. pushad                                     ;сохраняемсо
    3. .......                                       ;тело
    4. .......                                       ;функции
    5. popad                                      ;восстанавливаемсо                                
    6. mov esi,[param1]                       ; сохраняем  первый возвращаемый функцией параметр
    7. mov edi,[param2]                       ; сохраняем  первый возвращаемый функцией параметр
    8. ret                                          ;возврат обратно
    9. endp
    или второй вариант(с глобальными переменными):
    Код (Text):
    1. proc subfunction1,param1,param2
    2. pushad                                     ;сохраняемсо
    3. .......                                       ;тело
    4. .......                                       ;функции
    5. popad                                      ;восстанавливаемсо                                
    6. mov [global1],esi                       ; сохраняем  в глобальную переменную
    7. mov [global2],edi                       ; сохраняем  в глобальную переменную
    8. ret                                          ;возврат обратно
    9. endp
    При таком виде процедура не создает кадра стека т.е как я только что написал код - так и будет в листинге.
    Проблема возникла в случае, когда функция не такая уже и маленькая и без локальных переменных в ней не обойдешься. Сама процедура имеет вид:

    Код (Text):
    1. proc function
    2. locals
    3. some_variable1 dd ?
    4. some_variable2 dd ?
    5. some_variable3 dd ?
    6. endl
    7. ..........................
    8. ..........................
    9. ..........................
    10. ret
    11. endp
    фасм генерирует функцию такого вида:
    Код (Text):
    1. PUSH EBP
    2. MOV EBP,ESP
    3. SUB ESP,4
    4. .........................
    5. .........................
    6. .........................
    7. [b]leave [/b]
    8. ret
    т.е формирует кадр стека. При таком раскладе получается невозможна конструкция с передачей переменных обратно функции(конструкция1), которая вызывала подфункцию т.е при выходе очищается кадр стека.
    В общем-то сам вопрос: как можно в процедуре, в которой используются (locals endl) локальные переменные передать обратно вызывающей функции значения, при этом НЕиспользуя глобальные переменные ?
     
  2. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Код (Text):
    1. ret 0
    ред:
    Просто не используйте чистый RET.
     
  3. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    Принять параметром адрес буфера в стеке и скопировать результат в него?
     
  4. edemko

    edemko New Member

    Публикаций:
    0
    Регистрация:
    25 ноя 2009
    Сообщения:
    454
    Код (Text):
    1.         sub     esp,lalala
    2.         stdcall p1,1,2,3,esp
    3.  
    4. proc p1 param1, param2, param3, pVars
    5.         ...
    6.         mov     eax,[pVars]
    7.         mov     [eax],ebx
    8.         mov     [eax+4],ecx
    9.         mov     [eax],edx
    10.         ...
    11.         или
    12.         pop     dword[eax]
    13.         pop     dword[eax+4]
    14.         ...
    15.         или чего в голово придет
    16. endp
     
  5. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    common_up
    Если я правильно понял вопрос, то в варианте "конструкция 1" должно быть:
    mov [param1],esi ; сохраняем первый возвращаемый функцией параметр
    mov [param2],edi ; сохраняем первый возвращаемый функцией параметр

    , а не наоборот.
    Подобный способ возврата результатов из функции не принят. Более распространённым является вариант, предложенный iZzz32.
    Тем не менее, если хотите "остаться при своём", просто используйте в своих функциях cdecl, но вызывайте их, как stdcall. Тогда все переданные параметры будут оставаться в стеке:

    Код (Text):
    1. ;вызов cdecl-функции с двумя параметрами, как stdcall:
    2. stdcall subfunction1,eax,ecx
    3. pop ecx                                     ;\
    4. pop eax                                     ;_> выборка результатов из стека
    5.  
    6. ;cdecl-функция с двумя параметрами:
    7. proc subfunction1 c,param1,param2
    8. ;pushad                                     ;здесь логичнее было бы использовать
    9. ;.......                                       ;uses eax ebx
    10. ;.......                                       ;и т.д. в заголовке функции, указывая сохранять только необходимое.
    11. ;popad                                      ;pushad/popad — плохой стиль
    12. mov [param1], esi                       ; сохраняем  первый возвращаемый функцией параметр
    13. mov [param2], edi                       ; сохраняем  первый возвращаемый функцией параметр
    14. ret                                           ;возврат обратно
    15. endp
     
  6. qwe8013

    qwe8013 New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    198
    to l_inc
    У вас stdcall функция fasm вместо ret поставит retn xxx.
     
  7. qwe8013

    qwe8013 New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    198
    to common_up
    Чтобы к вас функции были cdecl нужно немного изменить макрос ret.
     
  8. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    qwe8013, с чего ж, если процедура как cdecl объявлена: proc subfunction1 c.
     
  9. common_up

    common_up New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2010
    Сообщения:
    85
    вот как на самом деле:
    Код (Text):
    1. proc ff
    2. locals
    3. variable dd ?
    4. endl
    5.             mov eax,0x10
    6.             mov [variable],eax
    7.             stdcall ww,[variable],[variable],[variable],[variable]
    8.             mov eax,[variable]
    9.         int 3
    10.             mov ebx,[esp-0x1C]
    11.             mov eax,[esp-0x10]
    12.            
    13.  
    14.  
    15. endp
    16.  
    17. proc ww,waaa,waaa1,waaa2,waaa3
    18. locals
    19. variable dd ?
    20. variable1 dd ?
    21. variable2 dd ?
    22. variable3 dd ?
    23. variable4 dd ?
    24. endl
    25.             mov  [variable],0x1
    26.             mov  [variable1],0x2
    27.             mov  [variable2],0x3
    28.             mov  [variable3],0x4
    29.             mov [waaa],0x5
    30.             mov [waaa1],0x6
    31.             mov [waaa2],0x7
    32.             mov [waaa3],0x8
    33.            
    34.             ret
    так что можно использовать в локальных переменных subfunction локальные OUTPUT_variables(так и сами локальные переменные, зарезервированные под использование самой сабфункцией), так и сами параметры функции, только при использовании параметров функции возникает проблема: если количество возвращаемых значений больше, чем количество параметров принимаемых сабфункцией - то облом, хотя можно это обойти, вызавая сабфункцию с нужными параметрами+несколько фейковых параметров, чтобы можно было вернуть необходимое кол-во параметров:)
    В общем полная свобода.

    дополнение:
    при вызове сабфункции с одним параметром значение последней локальной переменной = esp-0x10, при увеличении параметров функции добавляем к 10+4
     
  10. common_up

    common_up New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2010
    Сообщения:
    85
    в кулуарах все обсудили. Тему можно закрывать:) Всем спасибо за помощь
     
  11. Semiono

    Semiono New Member

    Публикаций:
    0
    Регистрация:
    27 ноя 2005
    Сообщения:
    752
    Подождите не закрывайте, я ещё её читаю! Тема хорошая :)