Есть DLL(ws2_32.dll), в которой параметры в некоторые функции передаются следующим образом: первый параметр - указатель на структуру - в регистре ecx второй параметр(int) - булевая переменная - через стек. Вопрос простой: что это за соглашение о передачи параметров и как его можно организовать в микрософтофском компиляторе? это не microsoft __fascall т.к. два параметра должны передаваться в регистрах ecx и edx соответсвенно, однако этого не наблюдается. похоже на __thiscall, но код то сишный...
Кто сказал, что сишный? В сорцах неоднократно встречаются классы. Chkdsk и иже с ним на ООП сделали, например.
А какие отличительный особенности си++`ного кода от простого сишного, кроме приатаченных стандартных классов?
shefchick Это может быть указатель на объект, классу которого принадлежит ф-ция. Написать на C++: Код (Text): MyClass *p; p -> mymethod(param); Но сначала нужно вызвать конструктор этого класса.
Угу, значит _thiscall...и функции это методы класса. А может компилятор поступать таким образом: зажать какую-нибудь глобальную переменную в регистр и использовать этот регистр постоянно?
shefchick Не может, тем более для экспортируемой функции. Компилятор строго соблюдает соглашения о вызове.
не не...она не экспортируемая - судя по семантике это конструктор... теоретическая ситуация: у нас есть глобальная константа -указатель на структуру, которая инициализируется один раз в начале программы и больше не меняется. И есть набор внутренних функций со стандартным соглашением вызова, допустим _cdecl, которые обращаются к этой структуре по этому глобальному указателю (bad style, понимаю, но все же...). Разве не может компилятор хранить этот указатель в регистре? И тогда функции юзают его обращаясь к регистру...Если не может, то по какой причине?...
Скорее всего внутренняя реализация использует глобальный объект, и экспортируемые функции вызывают методы этого объекта.
компилятор пишет в obj потом несколько obj собираются линкером в (например) exe в одном obj хранится в регистре указатель на глобал в другом - stack frame в третьем - это константа (например NULL) и как потом все это заставить вместе работать? пиши на асме и храни смело что угодно в регистре но если юзаешь чужие функции (например winAPI) или чужие библиотеки то знай и соблюдай их правила по регистрам
если ф-ция не єкспортируемая, компилятор может использовать custom calling conventions. Это типичная оптимизация в режиме LTCG.
народ, а дайте пример вызова таких ф-ций в си, а то у меня как-то некрасиво: Код (Text): FARPROC OpenFile; CHAR Path[MAX_PATH]; BYTE Temp[128] = "\0"; if hModule = LoadLibraryEx(Path, 0, LOAD_WITH_ALTERED_SEARCH_PATH) { OpenFile = GetProcAddress(hModule, "??0OpenFile@@ABC@ABCString@@0ABCDEFJQ2@Z"); __asm { xor eax,eax push eax push eax push eax push eax push eax push eax push eax lea ecx,Temp}; OpenFile(); }
можно деманглить имя и сделать объявление класса и юзать обычные указатели на функции-члены... и буфер под данные объекта отдельно не надо будет тока где етот код взял? он не компилицо и UnDecorateSymbolName выдала вот чего: private: __pascal OpenFile::OpenFile(signed char const &,ing,signed char const &,signed char const &,char,unsigned char,short,long, ?? __based() ::* const, ?? )const throw( ?? ) и зачем вызывать приватный конструктор хз 8-)
эээ ... имя это было выдуманное, так сказать псевдоним от "??0StartVirusInNuclearReactor@@AND@DestroyThePlanet@@054321GO!@Z" , деманглить мне не обязательно, надо просто вызвать ф-цию (передав указатель на буффер(ф-ция в него только пишет) в ecx), затем прочитать из него 1 байт, типа такого нет? (без асмовой вставки) (THISCALL)OpenFile(Temp, 0, 0, 0, 0, 0, 0, 0);
указатель на буффер - это this экземпляра класса, он и передается в ecx. а деманглить вот зачем... написал красивый с++ интерфейс: Код (Text): struct foo { void bar(); char buf[256]; }; int main() { // тип указателя на функцию-член typedef void (foo::* pf)(); // аллоцируем место под экземпляр класса char buf[sizeof(foo)]; // указатель на экземпляр класса foo * p = reinterpret_cast<foo*>(&buf[0]); // указатель на функцию-член pf f = &foo::bar; // reinterpret_cast<pf>(GetProcAddress(dll, "?bar@foo@@QAEXXZ"); // вызываем функцию (p->*f)(); } вызов __thiscall на валидном С++ компилируется и нет ассемблера... тока с конструкторами так низя... надо под них именованную функцию-член отводить.
Предупреждать надо было.. Я тоже думал зарыться в справочник по С++, узнать, возможна ли конструкция, что выдал undname. Подумал, что это приколы BCB.