Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Assembler > __fastcall -> cdecl


Автор: Rzonex 28.04.19, 11:53
Добрый день.

Подскажите как правильно сделать переход из соглашения __fastcall в соглашение cdecl?
Я хукаю __fastcall функцию и вызываю в хуке свою функцию cdecl. Делал так: резервировал буфер в целевом процессе, и в этот буфер записывал состояние регистров
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    MOV [ADR], ESI
    MOV [ADR], EAX
    MOV [ADR], ECX
    MOV [ADR], EDX
    MOV [ADR], EBX
    тут вызываю свою функцию cdecl и восстанавливаю регистры
    MOV ESI, [ADR]
    MOV EAX, [ADR]
    MOV ECX, [ADR]
    MOV EDX, [ADR]
    MOV EBX, [ADR]
    потом делаю PUSH ESI, чтоб вернуть адрес возврата в стек


Все это шаманство работало до поры, но сейчас спотыкается. Уверен, что все это жуткий костыль, и вобще так делать нельзя.
Подскажите пожалуйста как правильно сделать переходник? Чтобы после работы моей функции стек и регистры вернулись "как и было"?

Автор: Qraizer 28.04.19, 17:03
Никакого стандарта на соглашение __fastcall не существует. Каждый компилятор может трактовать его по-разному. Посему нет и определённых правил преобразования __fastcall во что-то иное, кроме тех, которые известны самому компилятору, выполнившему этот самый __fastcall. Если это соглашение описано в документации на компилятор, то следует изучить материал, и написать соответствующий переходник будет несложно. Но проще просто изначально отказаться от __fastcall. В противном случае шаманства, работающего на честном слове, не избежать.

Автор: Rzonex 28.04.19, 18:54
Спасибо разъяснил про фасткал. А если я например знаю, как передаются параметры? Есть же какие то общие принципы таких переходников, и в них врят-ли делали так же как я (сохраняли регистры в буфер)?
С вызовом моей функции на cdecl проблем нет - cdecl берет все из стека, загнать нужное туда не проблема. Проблема после ее работы восстановить регистры и стек в изначальное состояние...

Автор: Qraizer 28.04.19, 19:27
Цитата Rzonex @
Проблема после ее работы восстановить регистры и стек в изначальное состояние...
Ну а я-то об чём. Не зная соглашений целевого компилятора, ты ничего надёжного не сделаешь. Вот с чего ты взял, что сохранения регистров достаточно? Или даже, что сохранение регистров ничего не поломает? А вдруг компилятор через какой-нибудь EBP передаёт и возвращает ссылку на какие-то дополнительные стековые фреймы?

Автор: Rzonex 28.04.19, 21:14
Жаль :( Можно еще вопрос - как из стека верхнюю запись удалить? Можно засрать регистр сделав pop ESI например. А можно не засирая регистры ее удалить совсем?

Автор: core-i7 29.04.19, 02:38
Цитата Rzonex @
как из стека верхнюю запись удалить?

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    add  esp,4         ; удалить один аргумент
    sub  esp,4         ; зарезервировать dword в стеке

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)