· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.A&O —› экономия регистра

<< . 1 . 2 .

Посл.отвђт Сообщен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

Хотя, если разобраться, то всегда можно обойтись без этого. На ЯВУ функции имеют, как правило, одну точку входа.

<< . 1 . 2 .


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.044