The final calling convention that I haven’t gone over in depth is __thiscall.
Unlike the other calling conventions that I have previously discussed, __thiscall is not typically explicitly decorated on functions (and in most cases, you cannot decorate it explicitly).
As the name might imply, __thiscall is used exclusively for functions that have a this pointer – that is, non-static C++ class member functions. In a non-static C++ class member function, the this pointer is passed as a hidden argument. In Microsoft C++, the hidden argument is the first actual argument to the routine.
When a function is __thiscall, you will typically see the this pointer passed in the ecx register. In this respect, __thiscall is rather similar to __fastcall, as the first argument (this) is passed via register in ecx. Unlike __fastcall, however, all remaining arguments are passed via the stack; edx is not supported as an additional argument register. Like __fastcall and __stdcall, when using __thiscall, the callee cleans the stack (and not the caller).
In some circumstances, with non-exported, internal-only-to-a-module functions, CL may use ebx instead of ecx for this. For any exported __thiscall function (or a function whose address escapes a module), the compiler must use ecx for this, however.
Continuing with the previous examples, consider a function implementation like so:
class C { public: int c; __declspec(noinline) int ThiscallFunction1(int a, int b) { return (a + b) * c; } };
This function operates the same as the other example functions that we have used, with the exception that ‘c’ is a member variable and not a parameter.
The implementation of this function looks like so in assembler:
C::ThiscallFunction1 proc near a= dword ptr 4 b= dword ptr 8 mov eax, [esp+8] ; eax=b mov edx, [esp+4] ; edx=a add eax, edx ; eax=a+b imul eax, [ecx] ; eax=eax*this->c retn 8 ; return eax; C::ThiscallFunction1 endp
Note that [ecx+0] is the offset of the member variable ‘c’ from this. This function is similar to the __stdcall version, except that instead of being passed as an explicit argument, the ‘c’ parameter is implicitly passed as part of the class object this and is then referenced off of the this pointer.
Consder a call to this function like this in C:
C* c = new C; c->c = 3; c->ThiscallFunction1(1, 2);
This is actually a bit more complicated than the other examples, because we also have a call to operator new to allocate memory for the class object. In this instance, operator new is a __cdecl function that takes a single argument, which is the count in bytes to allocate. Here, sizeof(class C) is 4 bytes.
In assembler, we can thus expect to see something like this:
push 4 ; sizeof(class C) call operator new ; allocate a class C object add esp, 4 ; clean stack from new call push 2 ; 'a' push 1 ; 'b' mov ecx, eax ; (class C* c)'this' mov dword ptr [eax], 3 ; c->c = 3 call C::ThiscallFunction1 ; Make the call
Ignoring the call to operator new for the most part, this is relatively what we would expect. ecx is used to pass this, and this->c is set to 3 before the call to ThiscallFunction1, as we would expect, given the C++ code.
With all of this information, you should have all you need to recognize and identify __thiscall functions. The main takeaways are:
- ecx is used as an argument register, along with the stack, but not edx. This allows you to differentiate between a __fastcall and __thiscall function.
- Arguments passed on the stack are cleaned by the caller and not the callee, like __stdcall.
- For virtual function calls, look for a vtable pointer as the first class member (at offset 0) from this. (For multiple inheritance, things are a bit more complex; I am ignoring this case right now). Vtable accesses to retrieve a function pointer to call through after loading ecx before a function call are a tell-table sign of a __thiscall virtual function call.
- For functions whose visibility scope is confined to one module, the compiler sometimes substitutes ebx for ecx as a volatile argument register for this.
Note that if you explicitly specify a calling convention on a class member function, the function ceases to be __thiscall and takes on the characteristics of the specified calling convention, passing this as the first argument according to the conventions of the requested calling convention.
That’s all for __thiscall. Next up in this series is a brief review and table of contents of what we have covered so far with common Win32 x86 calling conventions.
Thanks for an excellent series on calling conventions. However, just wanted to point out that I think you have a typo in your list of Takeaways. You wrote:
“Arguments passed on the stack are cleaned by the caller and not the callee, like __stdcall.”
but since__thiscall works like __stdcall, the callee, not the caller, should clean up the stack.
Oh, and I would love to see a post about vtables and other class-related things.
Cheers!