c++ - 使用指针将代码翻译成 Pascal 中的程序集 - Delphi

标签 c++ arrays delphi assembly basm

我在下面有这段代码,我想将它翻译成 ASM,以便在 Delphi 中使用。

var
    FunctionAddressList: Array of Integer;

type TFunction = function(parameter: Integer): Integer; cdecl;

function Function(parameter: Integer): Integer;
var
    ExternFunction: TFunction;
begin
    ExternFunction := TFunction(FunctionAddressList[5]);
    Result := ExternFunction(parameter);
end;

它正常工作,但是当我尝试它的汇编版本时:

function Function(parameter: Integer): Integer; cdecl;
asm
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;

它应该可以工作,因为在 C++ 中它以两种方式工作:

void *FunctionAddressList;

_declspec(naked) int Function(int parameter)
{
    _asm mov eax, FunctionAddressList;
    _asm jmp dword ptr [eax + 5 * 4];
}

typedef int (*TFunction)(int parameter);
int Function(int parameter)
{
    TFunction ExternFunction = ((TFunction *)FunctionAddressList)[5];
    return ExternFunction(parameter);
}

但它在 Delphi 中不起作用。

在汇编版本中,它将数组乘以 4,因为它是数组每个元素之间的偏移大小,所以两个版本是等效的。

所以,我想知道为什么它不适用于 Delphi。在 Delphi 中,数组中 Integer 值之间的偏移大小与 C++ 不同?

我已经尝试了许多偏移量,如 1、2、4、6、8 等。还有许多类型的数组(指针数组;仅指针;整数数组等),我已经尝试了很多调用约定,cdecl 是唯一适用于非 asm 版本的约定,但对于 ASM,所有测试均无效。

谢谢。

最佳答案

第一个测试应用重现错误:

var
  FunctionAddressList: Array of Integer;

function Bar(parameter: Integer): Integer; cdecl;
begin
  ShowMessage('Bar '+IntToStr(parameter));
end;

function Foo(parameter: Integer): Integer; cdecl;
asm
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetLength(FunctionAddressList, 6);
  FunctionAddressList[5]:= Integer(@Bar);
  Foo(25);
end;

Bar地址定义正确,但问题是Delphi编译器为Foo生成了prologue和epilog,所以真正的Foo代码是

0046CD30 55               push ebp
0046CD31 8BEC             mov ebp,esp
Unit1.pas.46:             mov eax, FunctionAddressList
Unit1.pas.47:             jmp dword ptr [eax + 5 * 4]
0046CD3B 5D               pop ebp
0046CD3C C3               ret

导致堆栈损坏,参数错误,Bar返回地址错误。如果您仍然想这样做,请使用

function Foo(parameter: Integer): Integer; cdecl;
asm
  pop ebp
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;

关于c++ - 使用指针将代码翻译成 Pascal 中的程序集 - Delphi,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2173570/

相关文章:

delphi - 使用条款的差异

c++ - 为什么隐藏符号仍然添加到 DSO

c++ - 函数原型(prototype)和参数强制

javascript - COALESCE 加入 JAVASCRIPT

c# - 返回重复成员的最长子数组 C#

javascript - 如何转到 Angularjs 表达式中数组的下一项?

Delphi 堆栈错位 + com 编码 = 错误编码

database - 动态地在表单上放置复选框

c++ - std::initializer_list 和元素的求值顺序

c++ - 如何重定向到 C++ 中的另一个应用程序?