джампы после рета

Тема в разделе "WASM.BEGINNERS", создана пользователем babandr, 4 окт 2005.

Статус темы:
Закрыта.
  1. babandr

    babandr New Member

    Публикаций:
    0
    Регистрация:
    18 июн 2005
    Сообщения:
    29
    Адрес:
    Voronesh
    В листингах программ, написанных на Delphi, часто можно заметить после ret'а два jmp'а.

    Это не глюк Иды или Софтайса. Исследование Софтайсом показывает , что после рета перехода на эти джампы не происходит. Вопрос: зачем они нужны?
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Не обращай внимания - это стандартная дельфийская реализация try/except и try/finally. Посмотри в DeDe - во всех кликах VCL-компонентов сидят эти фишки.

    Попасть на эти JMP код может только при наличии исключения в теле функции или необработанного исключения в вызываемых ею функциях.

    Выглядит это так:
    Код (Text):
    1. @@try:
    2.     xor     eax,eax        ;установка SEH
    3.     push    ebp
    4.     push    @@jmp_to_SEH   ;это адрес JMP на стандартный обработчик
    5.     push    fs:[eax]
    6.     mov     fs:[eax],esp
    7. @@body:
    8.     ;...................   ;тело процедуры
    9. @@end_try:
    10.     ;...................   ;восстановление SEH-chain  
    11.     push    @@exit         ;пуш адреса завершения
    12. @@finally:
    13.         ;...................   ;здесь код блока finally..end
    14.     ret                    ;это "хитрый" RET = jmp @@exit
    15. @@jmp_to_SEH:
    16.     jmp  @@Std_SEH_Handler ;переход на стандартный SEH-обработчик
    17.     jmp  @@finally         ;сюда идет возврат из SEH для выполнения блока finally
    18. @@exit:
    19.     ;...................   ;код завершения = очистка стека
    20.     ret                    ;настоящий выход из процедуры
    При отсутствии исключения первый ("хитрый") RET работает просто как jmp @@exit, обходя два jmp. При наличии исключения код попадает на первый jmp и прыгает на стандартный обработчик, который решает что делать. Если продолжить обработку нельзя, то вызывается исполнение блока finally. Беря адрес первого jmp из SEH-chain, обработчик вычисляет адрес второго jmp, пушит новый адрес возврата и через второй jmp попадает на блок finally из которого по "хитрому" ret возвращается назад в обработчик.
     
Статус темы:
Закрыта.