I learned about calling conventions some time ago and wrote code to convert calls. The code is called from a special C # shell, the wrapper library uses emit reflection (cannot make Marshal.getdelegateforfunctionpointer work) to emit a new p / invoke method for the special naked stub method. It captures the parameters and then calls the actual method.
Here is the c code. I don't have a C # part :( I was learning assembler too at that time, so the code could suck :)
typedef struct
{
USHORT ParameterOneOffset;
USHORT ParameterTwoOffset;
} FastCallParameterInfo;
__declspec( naked,dllexport ) void __stdcall InvokeFast()
{
FastCallParameterInfo paramInfo;
int functionAddress;
int retAddress;
int paramOne, paramTwo;
__asm
{
pop retAddress;
pop paramInfo;
pop functionAddress;
movzx ecx, paramInfo.ParameterOneOffset;
cmp ecx,0;
je NoRegister;
movzx ecx, paramInfo.ParameterOneOffset;
dec ecx;
mov eax, 4;
mul ecx;
mov ecx, esp;
add ecx, eax;
mov eax, ecx;
mov ecx, [ecx];
mov paramOne, ecx;
add esp,4;
movzx edx, paramInfo.ParameterOneOffset;
dec edx;
cmp edx,0;
je ParamOneNoShift;
ParamOneShiftLoop:
mov ecx, eax;
sub ecx, 4;
mov ecx, [ecx]
mov [eax], ecx;
sub eax, 4;
dec edx;
jnz ParamOneShiftLoop;
ParamOneNoShift:
movzx ecx, paramInfo.ParameterTwoOffset;
cmp ecx,0;
je NoRegister;
movzx ecx, paramInfo.ParameterTwoOffset;
sub ecx, 2;
mov eax, 4;
mul ecx;
mov ecx, esp;
add ecx, eax;
mov eax, ecx;
mov ecx, [ecx];
mov paramTwo, ecx;
add esp,4;
movzx edx, paramInfo.ParameterTwoOffset;
dec edx;
cmp edx,0;
je NoRegister;
ParamTwoShiftLoop:
mov ecx, eax;
sub ecx, 4;
mov ecx, [ecx]
mov [eax], ecx;
sub eax, 4;
dec edx;
jnz ParamTwoShiftLoop;
NoRegister:
mov ecx, paramOne;
mov edx, paramTwo;
push retAddress;
jmp functionAddress;
}
}