Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a function using Delphi's register calling conventions from Visual C++?

I have a program written in Visual C++ 2012, and I was trying to call a function written in Delphi(which I don't have the source code). Here is the code in Visual C++:

int (_fastcall *test)(void*) = (int(_fastcall *)(void*))0x00489A7D;

test((void *)0x12345678);

But in the compiled code it actually was:

.text:1000113B                 mov     eax, 489A7Dh
.text:10001140                 mov     ecx, 12345678h
.text:10001145                 call    eax

And what I am excepting is:

.text:1000113B                 mov     ebx, 489A7Dh
.text:10001140                 mov     eax, 12345678h
.text:10001145                 call    ebx

I know 'fastcall' use EAX, ECX, EDX as parameters, but I don't know why Visual C++ compiler use EAX as a entry point. Shouldn't EAX be the first parameter(12345678h)?

I tried to call the delphi function in assembly code and it works, but I really want to know how to do that without using assembly.

So is that possible to let Visual C++ compiler generate code as what I am excepting? If yes, how to do that?

like image 524
Mickey Shine Avatar asked Dec 11 '22 17:12

Mickey Shine


1 Answers

Delphi's register calling convention, also known as Borland fastcall, on x86 uses EAX, EDX and ECX registers, in that order.

However, Microsoft's fastcall calling convention uses different registers. It does not use EAX at all. Instead it uses ECX and EDX registers for first two parameters, as described by the documentation.

So, with that information you could probably write some assembler to make a Delphi register function call from C++, by moving the parameter into the EAX register. However, it's going to be so much easier to let the Delphi compiler do that. Especially as I imagine that your real problem involves multiple functions and more than a single parameter.

I suggest that you write some Pascal code to adapt between stdcall and register.

function FuncRegister(param: Pointer): Integer; register; external '...';

function FuncStdcall(param: Pointer): Integer; stdcall;
begin
  Result := FuncRegister(param);
end;

exports
  FuncStdcall;

Then you can call FuncStdcall from your C++ code and let the Delphi compiler handle the parameter passing.

like image 180
David Heffernan Avatar answered Dec 24 '22 01:12

David Heffernan