Первая небольшая коррекция:
C имеет соглашение о вызовах cdecl; в основном выдвигает аргументы
в стек, имеет указатель возврата, затем переходит на какой-то адрес.
код по этому адресу извлекает аргументы из стека и продолжает его
веселый путь.
Вызываемый не извлекает аргументы из стека. Он читает параметры, не выталкивая их из стека. Вместо этого стек очищается вызывающей стороной. Это так, потому что в соглашении cdecl вызываемый не знает точное число параметров.
Теперь по вашему вопросу. Не существует строго определенного thiscall соглашения о вызовах. Подробнее здесь .
Gcc специфические:
thiscall почти идентичен cdecl: вызывающая функция очищает
стек, и параметры передаются в порядке справа налево.
Разница заключается в добавлении указателя this, который помещается на
стек последний, как если бы это был первый параметр в функции
Прототип
Вы не сможете выполнить свой трюк с сокрытием дополнительного аргумента this
и извлечением его внутри тела функции, особенно потому, что this
является первым аргументом функции. Если вы это скрываете - все остальные параметры функции будут смещены. Вместо этого вы можете (и должны ИМХО) объявить его как первый аргумент функции, и у вас будет прямой доступ к нему, без необходимости дополнительных уловок:
int bar(struct foo *cThis) {
cThis->baz = 0;
}
MSVC-конкретны:
... этот указатель передается в ECX, и вызываемый объект очищает
стек, отражающий соглашение stdcall, используемое в C для этого
компилятор и функции Windows API. Когда функции используют переменную
количество аргументов, это вызывающий, который очищает стек (ср.
Cdecl).
Здесь вы можете выполнить свой трюк, скопировав значение регистра ECX
в локальную переменную. Примерно так:
#define GETTHIS \
struct foo *cThis; \
_asm { \
mov cThis, ecx \
};
Это, однако, сложно и не всегда может работать. Причина этого заключается в том, что в соответствии с соглашениями о вызовах thiscall
/ stdcall
регистр ECX
зарезервирован для использования функции, поэтому компилятор может сгенерировать код, который перезаписывает значение регистра ECX
. Это может произойти даже до того, как вы вызовете макрос GETTHIS
.