Does anyone know to call a __thiscall function from C code? It's not a problem of garbled symbols (I have its address), it's a problem of passing this pointer in ecx. I thought declaring function as __stdcall and storing stuff in ecx with assembly magic would work, like this: __asm { mov ecx,self }
res=sub(a2,a3,a4,a5,a6,a7);
But code generated by visual studio overwrites ecx: dinput8.dll:66551153 mov ecx, [esp+10h] # my code
dinput8.dll:66551157 mov ecx, [esp+120h] # automatically generated by msvcs, thanks a lot
dinput8.dll:6655115E mov edx, [esp+11Ch]
dinput8.dll:66551165 push esi
dinput8.dll:66551166 push edi
dinput8.dll:66551167 push ebx
dinput8.dll:66551168 push ebp
dinput8.dll:66551169 push ecx
dinput8.dll:6655116A push edx
dinput8.dll:6655116B call off_66553344
Any ideas? I'd even be fine with writing some fake C++ class and calling its method, but unfortunately you can't specify an address of method of class when calling it...
Probably not doable properly without compiler support. __usercall(eax) would be nice to have (a certain decompiler has support for custom calling conventions like that). fastcall also works by putting things in registers, but that's not exactly what you need. If hacking the compiler or using some other compiler or frontend for it is not acceptable, you can probably do with some nasty C macros and more detailed __asm code.
Name:
Anonymous2010-09-26 4:44
Heh, I figured it out. Instead of setting ecx before the call to __thiscall function, I'm just calling some proxy function, setting ecx in it, eliminating changes it made to stack, and jumping to desired address. This still needs a bit more work (not storing this in global variables for thread safety, restoring stack properly instead of just pop ebx), but it's working and with almost no hacking. Here's working code for your enjoyment and enlightenment:
int globalself;
#define CAT2(a,b) a##b
#define CAT(a,b) CAT2(a,b)
#define DECLARE_THISCALL_CALLER(type,func,args) \
type (__stdcall *func) args; \
type __stdcall CAT(func,_caller) args { \
__asm{ pop ebp }; \
__asm{ mov ecx,globalself }; \
__asm{ jmp func }; \
} \
DECLARE_THISCALL_CALLER(signed int,subGylphsOriginal,(int,int,int,int,int,int));
signed int __stdcall subGylphs(int a2, int a3, int a4, int a5, int a6, int a7){
char s[0x100];
int self,res;
Doing this low-level tinkering with programs is so self-fulfilling. I never felt so good in some long time.
Name:
Anonymous2010-09-26 5:12
It took you less then an hour. I admire your quickness of thought.
Name:
Anonymous2010-09-26 5:28
>>4
Er, is this supposed to be an insult? Maybe I was doing something else at this time, or didn't post immediately after discovering this method and just went about using it for my greasy purposes instead?
Anyway, I'm struggling to eliminate that pop ebp now. From what I understand, what I popping from stack is a frame pointer (compiler generates push ebp; mov ebp, esp), so if someone enables the eliminate frame pointer optimization, it will all break, since I'll be popping something important off stack. What's strange though, is that neither __pragma(optimize( "y", off )), nor disabling frame pointer globally are removing this push ebp.
Name:
4さん2010-09-26 5:52
>>5
No, I was completely honest, though it surprised myself that I had to be. I wish you success in your noble quest to conjure the spirits of the x86 stack machine.
Name:
22010-09-26 6:34
>>5
So you just want to make a stdcall or cdecl(but not fastcall) convertor to thiscall?
My stdcall/cdecl->thiscall convertor approach is clean in that it doesn't really use any extra registers or extra stack space.
Name:
Anonymous2010-09-26 8:57
>>7
It's not clean in a way that you have to write a lot of boilerplate code pushing your args onto stack, while my solution allows you to use argument lists and compiler will generate all the pushing for you. Since I'm planning to use this a lot to aid myself in researching/debugging programs I didn't write, ease of use is top priority for me.