|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Июл 20, 2004 22:08:01 S_T_A_S_ От пролога и эпилога можно избавиться. Кстати fasm генерит точно такой же пролог и эпилог что и masm :-) А вобще, почти всегда в процедуре нужно юзать один ret, все остальные места где процедура могла бы завершиться лучше делать прыжок на этот ret, что как правило короче, но если в процедуре нет пролога и эпилога и ничего не push'иться на вход, то ret будет короче jmp на ret :-) |
|
|
Дата: Июл 20, 2004 22:18:50 Asterix Ну.. FASM может совсем другой пролог и эпилог генерить :) Какой хочешь :-) |
|
|
Дата: Июл 20, 2004 22:38:16 S_T_A_S_ > Ну.. FASM может совсем другой пролог и эпилог генерить :) По умолчанию вполне стандартный :-) |
|
|
Дата: Июл 20, 2004 23:29:00 cresta > Во всех процедурах, куда пробовал втыкать @SomeLabel:: есть локальные переменные. Это значит, что на входе выполняется что-то вроде: push ebp mov ebp, esp sub esp, XX на выходе, соответственно обратные действия, так что если войти в середину, то при выходе должны быть проблемы. > в некоторых случаях (обычно callback) возвращается нормально. А иногда программа вылетает. Почему вылетает не всегда - не знаю. Да тут сложно что-то сказать.. Может, ESP постепенно увеличивается.. Можно попробовать последить за состоянием этого регистра на выходе - возможно это прояснит ситуацию. > А вот тут я ещё поизвращался: И помоему работает надёжно [..] Причем через push 0 или push 1 или push 2 можно конкретно определить откуда пришли и определённо возвращаться в то же место Хм, а если случайно наткнуться на данные? 0 - вполне обыченю user32.dll, например использует DCBAABCDh для проверки корректности стека после вызоваWindowProc. ihmo в таких случаях всегда можно разделить одну процедуру на 2 или более частей и исключить такие проверки - это может быть даже меньше места занимать будет, к тому же надёжнее. Asterix > По умолчанию вполне стандартный :-) Гы, а я по у молчению никогда не пользовался. даже в MASM свои пролог/эпилог делал, но там геморрой 8-() |
|
|
Дата: Июл 21, 2004 01:36:46 S_T_A_S_ Хм, а если случайно наткнуться на данные? Но ведь непосредственно перед ret в вершине стека не может быть данных, обязан быть адрес возврата. Если по какой-то причине там оказались данные - то программа вылетит и без моего участия. Возможно user32 что-то и мутит, но ведь я вставляю это в свой код и знаю, что если данные(0,1,2) то это моя отметка. |
|
|
Дата: Июл 21, 2004 02:36:59 · Поправил: Oleg_SK cresta Показанный вами вариант будет работать надежно только в том случае, если код который будет выполняться на отрезке между внутренней точкой входа и точкой выхода из процедуры, не будет обращаться к локальным переменным этой процедуры. В своем прошлом посте я предположил, что в процедуре нет локальных переменных. Если же они там есть, то, как и указал S_T_A_S_, будут проблемы. Чтобы их избежать, я сейчас вижу три пути (при условии, что необходимо выполнить код от внутренней точки входа до конца процедуры): 1) Это тот путь, которым вы пользовались первоначально. По моему, это не плохой вариант, т.к. у процедуры, по идее, должен быть один вход и один выход; 2) Во внутренней точке входа можно произвести настройку стекового кадра, например: ;=========================================== FirstProc proc param1:DWORD,param2:DWORD ; ;здесь какой-то код ; Call @SomeLabel ; FirstProc endp ;================================== SomeProc proc param1:DWORD,param2:DWORD ; ;пропускаемый в данном случае кусок процедуры ; jmp short Continue @SomeLabel:: ;Здесь производится настройка стекового кадра. Если мы попали в процедуру с основной точки входа, то этот код не выполняется. ; Continue: ; SomeProc endp 3. Как уже говорил S_T_A_S_, нужно разделить процедуру на несколько частей. Это, IMHO, самый лучший вариант, с точки зрения надежности. |
|
|
Дата: Июл 21, 2004 11:02:31 Oleg_SK Получается исходный вариант лучше всего. Доведенный до такого примерно состояния: ;=========================================== FirstProc proc param1:DWORD,param2:DWORD ;здесь какой-то код mov jmpVar, @SomeLabel2 Call SomeProc ; FirstProc endp ;================================== SomeProc proc param1:DWORD,param2:DWORD mov eax,jmpVar test eax,eax jnz eax ; @SomeLabel1:: @SomeLabel2:: @SomeLabel3:: ; ; mov jmpVar,0 ret SomeProc endp Нет проблем со стеком, от локальных переменных не зависим и добавляется минимум кода. Спасибо всем. |
|
|
Дата: Июл 21, 2004 13:21:05 cresta jnz eax Для семейства процессоров 80x86 такой команды не существует. Ее можно заменить следующей парой команд: jz Continue jmp eax Continue: |
|
|
Дата: Июл 21, 2004 17:25:55 Да, принцип таков. Просто писал тут бегом :) |
|
|
Дата: Июл 21, 2004 19:01:37 cresta > Но ведь непосредственно перед ret в вершине стека не может быть данных, обязан быть адрес возврата. Если по какой-то причине там оказались данные - то программа вылетит и без моего участия. Да, так должно быть. Но я исходил из того, что в некоторых случаях почему-то вылетает. Думаю - что-то не вспорядке со стеком. Поскольку это МАСМ и стандартный пролог, то используется EBP-based стековый фрейм, и вероятно в каких-то случаях происходит работа со стеком вызывающей ф-ции. Именно из-за EBP программа и не вылетает постоянно (был бы ESPБ то ничег б не работало imho), а лишь время от времени, когда как-то портятся локальные переменные другой процедуры. |
|
|
Дата: Авг 11, 2004 00:51:50 Почему бы не сделать две точки входа: SomeProc: Enter 3*4, 0 ... ; some code .intomid_: ... ; another code Leave Ret 2*4 .intomid: Enter 3*4, 0 ... ; some init Jmp .intomid_ А потом делать так: Push b Push a Call SomeProc Push b Push a Call SomeProc.intomid Хотя, если разобраться, то всегда можно обойтись без этого. На ЯВУ функции имеют, как правило, одну точку входа. |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.044 |