4

我有一个用 Visual C++ 2012 编写的程序,我试图调用一个用 Delphi 编写的函数(我没有源代码)。下面是 Visual C++ 中的代码:

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

test((void *)0x12345678);

但在编译后的代码中,它实际上是:

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

我所例外的是:

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

我知道“fastcall”使用 EAX、ECX、EDX 作为参数,但我不知道为什么 Visual C++ 编译器使用 EAX 作为入口点。EAX不应该是第一个参数(12345678h)吗?

我试图在汇编代码中调用 delphi 函数并且它可以工作,但我真的很想知道如何在不使用汇编的情况下做到这一点。

那么是否有可能让 Visual C++ 编译器生成我所例外的代码?如果是,该怎么做?

4

1 回答 1

13

Delphi 的寄存器调用约定,也称为 Borland fastcall,在 x86上按顺序使用EAX、EDX 和 ECX 寄存器。

但是,微软的 fastcall 调用约定使用不同的寄存器。它根本不使用 EAX。相反,它使用 ECX 和 EDX 寄存器作为前两个参数,如文档所述

因此,有了这些信息,您可能可以编写一些汇编register程序,通过将参数移动到EAX寄存器中来从 C++ 进行 Delphi 函数调用。然而,让 Delphi 编译器来做这件事会容易得多。特别是当我想象您的真正问题涉及多个功能和多个参数时。

我建议你写一些 Pascal 代码来适应stdcallregister

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

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

exports
  FuncStdcall;

然后您可以FuncStdcall从您的 C++ 代码中调用并让 Delphi 编译器处理参数传递。

于 2013-03-11T15:22:18.790 回答