First minor correction:
C has a calling convention cdecl; basically pushes arguments onto the stack, has a return pointer, then goes to some address. the code at this address pushes arguments from the stack and the fun path continues.
The calling command does not pop arguments from the stack. It reads the parameters without unloading them from the stack. Instead, the stack is cleared by the caller. This is because in the cdecl convention the caller does not know the exact number of parameters.
Now about your question. There is no strictly defined thiscall calling convention. More details here .
Gcc specific:
thiscall is almost identical to cdecl: the calling function clears the stack, and the parameters are passed in order from right to left. the difference is adding this pointer, which is the last stack, as if it were the first parameter in the Prototype function
You cannot do your trick by hiding the extra this
argument and retrieving it inside the function body, especially because this
is the argument to the first function. If you hide it, all other parameters of the function will be shifted. Instead, you can (and should IMHO) declare it as the first argument to the function, and you will have direct access to it, without the need for additional tricks:
int bar(struct foo *cThis) { cThis->baz = 0; }
MSVC specific:
... this pointer is passed to ECX, and it is the caller who clears the stack that mirrors the stdcall convention used in C for this compiler and in the Windows API functions. When functions use a variable number of arguments, it is the caller that clears the stack (see Cdecl).
Here you can do your trick by copying the value of the ECX
into your local variable. Something like that:
#define GETTHIS \ struct foo *cThis; \ _asm { \ mov cThis, ecx \ };
This, however, is complex and may not always work. The reason for this is that, according to the calling conventions of thiscall
/ stdcall
ECX
reserved for using the function, so the compiler can generate code that overwrites the value of the ECX
. This can happen before you call the GETTHIS
macro.