使用指针将代码转换为 Pascal 中的程序集 - Delphi

发布于 2024-08-19 15:26:09 字数 1225 浏览 12 评论 0原文

我下面有这段代码,我想将其转换为 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 中不起作用。

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

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

我已经尝试过许多偏移量,如 1、2、4、6、8 等。以及许多类型的数组(指针数组;仅指针;整数数组等),并且我尝试了许多调用约定, cdecl 是唯一适用于非 asm 版本的,但使用 ASM 时,所有测试都不起作用。

谢谢。

I have this code below, and I want to translate it to ASM, to use in Delphi too.

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;

It works normaly, but when I try its Assembly version:

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

It is supposed to work, because, in C++ it works in both ways:

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);
}

But it doesn't work in Delphi.

In the Assembly version, it multiplies the array to 4, because it's the offset size between each element of the array, so both versions are equivalent.

So, I want to know why it doesn't work with Delphi. In Delphi, the offset size between Integer values in a array is different than C++?

I've already tried many offsets, as 1, 2, 4, 6, 8, etc. And many types of Array (Array of Pointer; only Pointer; Array of Integer, etc), and I've tried many calling conventions, and cdecl was the only that worked with the non-asm version, but with ASM, all the tests didn't work.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情定在深秋 2024-08-26 15:26:09

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

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生成序言和结尾,所以真正的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;

First test app to reproduce error:

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;

The Bar address is defined correctly, but the problem is that Delphi compiler generates prologue and epilog for Foo, so real Foo code is

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

As a result the stack is corrupted, the parameter is wrong and Bar return address is wrong. If you still want to do the trick, use

function Foo(parameter: Integer): Integer; cdecl;
asm
  pop ebp
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;
空城旧梦 2024-08-26 15:26:09

整数数组并不是你想象的那样。它是一个自动管理的动态数组。

您应该使用 FunctionAddressList: ^Pointer; 尝试相同的操作 - 但请注意,您必须进行手动分配和释放。

Array of Integer is not what you think it is. It's an automatically managed dynamic array.

You should try the same using FunctionAddressList: ^Pointer; -- note however that you will have to do manual allocation and deallocation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文