Здравствуйте, уважаемые форумчане. Из того, что должно быть на видном месте в FAQ. Я читал, смотрел и не нашел, хотя когда-то где-то здесь видел (и уже забыл). Есть какие-то регистры, которые не следует изменять между вызовами Win32 API функциями. Помимо ESI, EDI кажется EBX и/или ECX. То есть если я буду свободно менять значение этого регистра, то программа может себя неправильно повести при очередном вызове некоторых функций API. Я прав, есть такие регистры (из числа регистров общего назначения) или я заблуждаюсь? С уважением, mc-black
Во, ESP и EBX! Спасибо за ценную подсказку! А насчет EAX, ECX, EDX можете подсказать примеры функций, где их менять нельзя? Или где это можно прочесть, в MSDN подозреваю, что про это ни слова.
Я давным давно открывал в отладчике интересующую функцию, смотрел там в начале push edi push esi push ebx и в конце pop ebx pop esi pop edi ок, значит эти регистры свободны, мона юзать. Даже списочек составлял для разных Api
Вообще-то есть соглашение, по которому все __stdcall функции обязаны сохранять значения регистров ebx, esi, edi, ebp (и извлекать из стека все параметры, восстанавливая значение стека). Все остальные регистры эти функции могут менять по своему усмотрению, не обращая внимания на их значения. Суть не в том, чтобы сохранять значения между вызовами API, а в том, чтобы сохранять значения этих регистров для вызывающей функции. Например, есть ваша call-back функция WindowProc. Вот она обязана сохранить значения этих регистров. Иначе после возврата из функции, можно словить исключение. API функции обычно __stdcall.
Наверное имелось ввиду какие еще регистры использует функция. Вдруг ecx с edx свободны от юзанья в какой то апишке - это ж круто, на 2 push pop меньше до вызова апи для сохранения своих регистров
dinoweb прав, большинство вызовов WinAPI stdcall Есть fastcall, но они вам встретятся не скоро. Сохранять регистры ebx, esi, edi, ebp Сохранять esp не надо. Его нужно восстанавливать, забирая из стека переданные аргументы. Таких нет, в своем коде можете менять любые регистры, главное, восстанавливать их при выходе из процедуры, если она вызывается в соответствии с определенным соглашением. 9Demon, иногда лучше жевать.
ormoulu Dinoweb уже сказал все что надо по этой теме, нах ты еще раз повторяешь ? Не понял. Иди в жопу умник..
Мне показалось, что чуть более подробное объяснение новайсу не повредит. Объясняю: если сделать так, как ты предлагаешь (открыть в отладчике и посмотреть, какие сохраняются в начале) можно серьезно облажаться, поскольку есх, например, __stdcall сохранять не обязан.
В XP к примеру есть такие функции, не меняющие ecx и edx GetModuleHandleA(0) GetCommandLineA GetCurrentProcess GetCurrentProcessId GetCurrentThread GetCurrentThreadId
А если между push ecx и pop ecx у тебя будет mov [esp], ЛЕВАЯ_ХРЕНЬ? Плюс, если ты не увидишь push/pop edi или ebp, то что, ты их будешь сохранять перед вызовом? И потеряешь те самые байты, которые хочешь сэкономить.
9Demon Просто по дизасму не всегда получится определить это. Например Zw-стабы, явно меняют только Eax. Но ядро изменяет Ecx и Edx. А вот флажки(EFlags) сохраняет. Таким образом если в коде используются сервисы, то Ecx и Edx не сохраняются. Эта частный случай закрытых ветвлений(например Call Arg) - таких, в которых адрес ветвления не определён(сискол тоже процедурное ветвление), например колбеков.
mc black Соглашение о регистрах - только для CALLBACK процедур. Тех процедур, адрес которых передаётся в Win32: WindowProc DialogProc ThreadProc EnumWindowsProc EnumFontsProc и т.п. Ещё надо сбросить флаг направления перед возвратом в Win32, но только если он был установлен. По умолчанию DF=0 в Win32. Общее правило: если адрес процедуры ставится в какую-либо структуру Win32 и затем передаётся в Win32 или адрес процедуры передаётся непосредственно как параметер вызова Win32 -- регистры в такой процедуре должны быть сохранены. Положив значения в ESI,EDI,EBX,EBP - можно быть уверенным что это сохранится между вызовами API: Код (Text): mov esi, [hWnd] invoke InvalidateRect, esi, 0, 0 invoke UpdateWindow, esi
Ребята, всем огромное спасибо за участие и первоклассную помощь! Теперь всё стало ясно. Да, мне как раз надо сохранять ESI, EDI, EBX, EBP, так как я собрался сделать маленькую библиотечку, построенную по подобию masm32.lib. Эти функции я хотел бы вызывать по соглашению stdcall, помнил раньше чётко только про esi, edi (ebp мне бы в голову не пришло менять). Но где-то смутно помнил, что чего-то ещё менять не следует, мне про это чётко написали, теперь когда буду использовать ebx, не забуду добавить к proc: uses ebx (или push / pop ebx). Это главное, что меня смущало. Ещё раз всем СПАСИБО!