|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Июл 19, 2004 23:23:53 Часто встречается(в т.ч. и на форуме) такие диалоги: -"...экономим 1 регистр..." -"...зато твой код длиннее на n байт...". Объясните, плиз что даёт экономия регистра, и что зависит от количества задействованных регистров? |
|
|
Дата: Июл 20, 2004 00:11:28 Смотря какой регистр 1) даёт возможность не сохранять его 2) можно использовать его под другие цели 3) просто кайф от победы над кодом |
|
|
Дата: Июл 20, 2004 00:33:51 · Поправил: cresta Т.е. выгода (в плане скорости или размера) может быть только в случае возникновения нехватки регистров(eax,ebx,ecx,edx) и связанной с этим необходимостью дополнительных пересылок в память(или стек) и обратно? А в остальных случая остаётся только кайф? |
|
|
Дата: Июл 20, 2004 01:15:36 · Поправил: S_T_A_S_ У процессора есть всего 8 регистров общего назначения. Один (ESP) занят под указатель на стек, так что в большенстве случаев непосредственно не используется. Как правило, ещё и EBP отводят как указатель на стековый кадр - локальные переменные в ф-циях. (Хотя последнее, в общем-то не обязательно делать, к ним можно и через ESP обращаться, но каждая команда тогда длиннее на байт будет) Итого остаётся 6 регистров, в них уже можно хранить что угодно. (хотя обычно есть некоторая специализация) Так вот, к вопросу :) Любая программа оперирует с различными данными. Эти данные могут находиться в памяти, но в этом случае доступ к ним происходит довольно медленно. К тому же, некоторые операции возможны только над данными находящимися в регистрах. Поэтому данные, к которым в данный момент требуется максимально быстрый доступ, хранят в регистрах. Теперь предположим, для какой-то операции желательно 8 регистров. Как быть? Приходится один или 2 постоянно сохранять на стеке или ещё где - это сильно замедляет код. Если же код переписать таким образом, что будет нужно 5 регистров, то выполнение ускорится. иногда очень сильно. В общем-то, это основа оптимизации кода по скорости - как можно меньше использовать ОЗУ, стараться все вычисления делать в регистрах. Если кажется, что остаётся только кайф, то можно ещё для каких-то целей использовать регистр. |
|
|
Дата: Июл 20, 2004 02:47:40 · Поправил: cresta S_T_A_S_ Т.е. как я понял, желательно смещать баланс хранения данных "память-регисты" в сторону регистров. Так вот, к вопросу :) Ну тогда, пока народ не очень сердитый (и не отсылает в поиск),ещё один вопрос: В электронной версии Юрова (других у меня просто нет :(() нет ничего о такой простой вещи: jmp на произвольный адрес. Несколько раз мне требовалось пререйти в другую процудуру, причем не на начало, а в середину, и я делал так: ;===========================================
FirstProc proc param1:DWORD,param2:DWORD
;
;здесь какой-то код
;
mov jmpVar,1 ;переменная для проверки
push eax
push edx
Call SomeProc
;
FirstProc endp
;==================================
SomeProc proc param1:DWORD,param2:DWORD
cmp jmpVar,1 ;проверка, откуда мы пришли
je @SomeLabel ;если из FirstProc,то на @SomeLabel
;
;пропускаемый в данном случае кусок процедуры
;
@SomeLabel:
mov jmpVar,0 ;обнуляем переменную
;
;
SomeProc endp
;=================================================Как можно заменить такую конструкцию на jmp<адрес метки @SomeLabel>или Call <адрес @SomeLabel> ? Наверное должен быть способ покрасивее. |
|
|
Дата: Июл 20, 2004 03:48:24 cresta Для того, чтобы можно было прыгнуть внутрь процедуры на какую-либо метку в ее теле, эта метка должна быть объявлена как глобальная, например (MASM32): ;=========================================== FirstProc proc param1:DWORD,param2:DWORD ; ;здесь какой-то код ; Call @SomeLabel ; FirstProc endp ;================================== SomeProc proc param1:DWORD,param2:DWORD ; ;пропускаемый в данном случае кусок процедуры ; @SomeLabel:: ; ; SomeProc endp ;================================================= |
|
|
Дата: Июл 20, 2004 07:22:38 Прыгать внутрь процедуры немного рискованно - можешь пропустить какой-то кусок, который важен для выхода из процедуры. В таких случаях лучше пересмотреть логику программы и сделать пару функций, которые сделают код читаемым, но длинее на пару байт... Хотя это, конечно, кто как... персональная установка. |
|
|
Дата: Июл 20, 2004 09:36:52 это чисто дзенский изврат, современные процы, точнее их быстродействие от этого ничего не теряют |
|
|
Дата: Июл 20, 2004 09:37:32 а вот если какие нить пик контролеры програмить, то тут данное умение будет даже очень кстати |
|
|
Дата: Июл 20, 2004 14:00:47 Oleg_SK @SomeLabel:: Двух двоеточий достаточно для глобального объявления, я так понял. Спасибо. CARDINAL Да это от ВЕ49 осталось, там вечно не хватало памяти и приходилось так извращаться. Сейчас необходимости нет, просто вижу, что кусок кода уже есть, не хочется писать его снова. Прыгнул и всё. |
|
|
Дата: Июл 20, 2004 14:08:45 · Поправил: S_T_A_S_ cresta > Т.е. как я понял, желательно смещать баланс хранения данных "память-регисты" в сторону регистров. В общем-то, да. Вобще-то я щас почитал, что написал раньше на сон грядущий.. Гхм. Вроде такая простая IMHO вещь, а а сложно объяснить.. Я как учился: процессор - это отдельный блок, регистры находятся внутри, а память - снаружи. Поэтому мне кажется совершенно логичным использовать (внешнюю) память только когда это действительно нужно. > Несколько раз мне требовалось пререйти в другую процудуру, причем не на начало, а в середину, и я делал так: IMHO в данном случае - это есдинственное решение (не меняя SomeProc proc) Вариант, предложенный Oleg_SK работать не будет (хотя про глобальные метки верно), т.к. при входе в середину SomeProc не будет происходить формирование стекового фрейма, зато он будет очищаться при выходе. Нарушение баланса стека гарантированно. Хотя, если SomeProc не имеет локальных переменных, то так делать можно. В общем, зависит как определены option prologue и option epilogue. Дело в том, что ret в MASM может произвести больше кода, чем C3h Можно попробовать так: ;=========================================== FirstProc proc param1:DWORD,param2:DWORD ; ;здесь какой-то код ; Call @SomeLabel ; FirstProc endp ;================================== SomeProc2 proc param1:DWORD,param2:DWORD ; здесь формируется стековый кадр, аналогичный SomeProc jmp @SomeLabel SomeProc endp SomeProc proc param1:DWORD,param2:DWORD ; ;пропускаемый в данном случае кусок процедуры ; @SomeLabel:: ; ; ret ; здесь стековый кадр очищается SomeProc endp ;================================================= > это от ВЕ49 осталось.. Эта та штука, что была до МК 62 ? :) |
|
|
Дата: Июл 20, 2004 15:15:15 S_T_A_S_ > Дело в том, что ret в MASM может произвести больше кода, чем C3h А причем тут masm? ;-) ret с коррекцией стека будет точно такой же что и в fasm ;-) |
|
|
Дата: Июл 20, 2004 19:51:51 Asterix > А причем тут masm? ;-) Есть такая штука, включенная по умолчанию: option prologue:PrologueDef option epilogue:EpilogueDef Это значит, что не только ret n быдет, но ещё и pop ebp и add esp,XX врозможен |
|
|
Дата: Июл 20, 2004 20:02:30 S_T_A_S_ В крайнем случае можно использовать retn, но оччень осторожно :-) |
|
|
Дата: Июл 20, 2004 21:45:39 · Поправил: cresta S_T_A_S_ Нарушение баланса стека гарантированно. Хотя, если SomeProc не имеет локальных переменных, то так делать можно. Во всех процедурах, куда пробовал втыкать @SomeLabel:: есть локальные переменные. Если Call @SomeLabel, то в некоторых случаях (обычно callback) возвращается нормально. А иногда программа вылетает. Почему вылетает не всегда - не знаю. А вот тут я ещё поизвращался: И помоему работает надёжно ;===========================================
FirstProc proc param1:DWORD,param2:DWORD
;
;здесь какой-то код
;
push 0 ;из нулевого адреса вызываться
jmp @SomeLabel ;функция, содержащая @SomeLabel
@Return:: ;никак не может
;
FirstProc endp
;==================================
SomeProc proc param1:DWORD,param2:DWORD
;
;пропускаемый в данном случае кусок процедуры
;
@SomeLabel::
;
;
pop eax ;непосредственно перед ret проверяем
test eax,eax ;куда возвращаемся
jnz @F ;если нулевой адрес, значит уходим как и пришли -
jmp @Return ;через jmp
@@:
push eax ;если не ноль - был нормальный вызов процедуры
ret
SomeProc endp
;=================================================
Причем через push 0 или push 1 или push 2 можно конкретно определить откуда пришли и определённо возвращаться в то же место.Т.е. push 0 (@Return0) в одном месте push 1 (@Return1) в другом и т.д. Эта та штука, что была до МК 62 ? :) Если речь о калькуляторах - то нет. Были такие однокристальные ЭВМ по моему серии КР 1816. Там была встроенная ПЗУ на 1024 байт. И туда надо было запихать ну очень много... |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.116 |