FreePascal x64 上系统单元函数的汇编调用

2024-05-14

我有一些 Delphi/汇编代码,可以在 Win32、Win64 和 OSX 32 上编译并正常工作(XE2)。但是,由于我需要它在 Linux 上工作,所以我一直在考虑编译它的 FPC 版本(到目前为止,Win32 /64、Linux32/64)。

总的来说,它运行良好,但我无法开始工作的一件事是调用/跳转到 DelphiSystem单元函数,例如:

  jmp System.@FillChar

这似乎对 FPC Win32/Linux32 具有预期的效果,但是fails有一个例外在 FPC Win64/Linux64 上。 (我非常熟悉平台之间的调用约定差异,所以不认为这是原因。)

在 x64 平台的 FPC 上执行此操作的正确方法是什么?

[Edit1]--- 为了回应大卫的评论,这里有一个简化的程序来说明问题(至少我希望它能如此准确):

program fpcx64example;
{$IFDEF FPC}
  {$MODE DELPHI}
  {$ASMMODE INTEL}
{$ELSE}
  {$APPTYPE CONSOLE}
{$ENDIF}

procedure FillMemCall (p: pointer; len: longword; val: byte);
asm
  // this function and the System function have the same parameters
  // in the same order -- they are already in their proper places here
  jmp System.@FillChar
end;

function MakeString (c: AnsiChar; len: longword): AnsiString;
begin
  Setlength (Result, len);
  if len > 0 then FillMemCall (PAnsiChar(Result), len, byte(c));
end;

begin
  try
    writeln (MakeString ('x',10));
  except
    writeln ('Exception!');
  end;
end.

使用 FPC 编译: [Win32:] fpc.exe fpcx64example.dpr, [Win64:] ppcrossx64.exe fpcx64example.dpr, [Linux32:] fpc.exe -Tlinux -XPi386-linux- -FD[path]\FPC\bin\i386-linux fpcx64example.dpr, [Linux64:] ppcrossx64.exe -Tlinux -XPx86_64-linux- -FD[FPCpath]\bin\x86_64-linux fpcx64example.dpr.

与 Delphi (Win32/64) 配合良好。对于FPC,去除jmp System.@FillChar上面消除了 x64 上的异常。

解决方案(感谢 FPK):

Delphi 和 FPC 在完全相同的条件下不会为函数生成堆栈帧,因此RSP两者编译的版本中,register 可能有不同的对齐方式。解决方案是避免这种差异。对于上面的 FillMemCall 示例,一种方法如下所示:

{$IFDEF CPU64} {$DEFINE CPUX64} {$ENDIF} // for Delphi compatibility
procedure FillMemCall (p: pointer; len: longword; val: byte);
  {$IFDEF FPC} nostackframe; {$ENDIF} //Force same FPC behaviour as in Delphi
asm
  {$IFDEF CPUX64}
    {$IFNDEF FPC} .NOFRAME {$ENDIF} // To make it explicit (Delphi)...
    // RSP = ###0h at the site of the last CALL instruction, so
    // since the return address (QWORD) was pushed onto the stack by CALL,
    // it must now be ###8h -- if nobody touched RSP.
    movdqa xmm0, dqword ptr [rsp + 8] // <- Testing RSP misalignment -- this will crash if not aligned to DQWORD boundary
  {$ENDIF}
  jmp System.@FillChar
end;

这并不完全漂亮,但它现在适用于 Delphi 和 FPC 的 Win/Linux 32/64。


简短的回答:正确的方法是使用 call 指令。

长答案:x86-64 代码要求堆栈是 16 字节对齐的,因此 FillMemCall 在入口点包含编译器生成的 sub rsp,8 和在出口处的 add rsp,8 (其他 8 个字节由呼叫/回传对)。另一方面,Fillchar 是手工编码的汇编程序,并使用 nostackframe 指令,因此它不包含编译器生成的 sub/add 对,一旦 fillchar 离开,堆栈就会混乱,因为 FillChar 之前不包含 add rsp,8 ret 指令。

诸如使用 FillMemCall 的 nostackframe 指令或在执行 jmp 之前调整堆栈之类的解决方法可能是可能的,但可能会被任何未来的编译器更改所破坏。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreePascal x64 上系统单元函数的汇编调用 的相关文章

随机推荐

  • Laravel:类控制器不存在

    我创建了一个简单的控制器并定义了一个函数 但是当我运行它时 它返回一个错误 指出控制器不存在 在我的 web php 中分配一条路线
  • main() 还可以接受其他参数吗?

    我最近在搜索 C 环境变量时发现了以下内容 int main int argc char argv char envp 我四处搜寻 找不到关于我的问题的任何结论 所有可用的论据是什么main 可以接受吗 C99 和 C11 标准草案允许实现
  • PostgreSQL:有效地将 JSON 数组拆分为行

    我有一个表 表 A 其中包含一个包含 JSON 编码数据的文本列 JSON 数据始终是一个包含一到几千个普通对象的数组 我有另一个表 表 B 其中有几列 包括数据类型为 JSON 的列 我想从表 A 中选择所有行 将 json 数组拆分为其
  • 可能有相同的合同,相同的绑定,相同的地址,但不同的端口?

    我有需要通过 basicHTTPBinding 进行通信的手持设备 我有合同 一切都按照广告进行 我需要扩展它以轻松支持测试环境 培训 当然还有生产的更改 我选择了端口路线 认为我可以公开具有端口差异的不同端点 并根据端口决定我想要来自哪个
  • 从字典中绘制直方图

    我创建了一个dictionary计算 a 中出现的次数list每个键的内容 我现在想绘制其内容的直方图 这是我想要绘制的字典的内容 1 27 34 1 3 72 4 62 5 33 6 36 7 20 8 12 9 9 10 6 11 5
  • asp.net 将值从 JS/jquery 传递到 C# 背后的代码

    我已经尝试了 所有 可能的方法 将 screen width vlaue 从 aspx 页面上的 JS 脚本发送到后面代码中的 c 虽然我可以看到 screen width 被正确分配 但它永远不会分配给我的隐藏字段价值
  • 如何查找列中未使用的ID? [复制]

    这个问题在这里已经有答案了 可能的重复 SQL查询查找丢失的序列号 https stackoverflow com questions 1057389 sql query to find missing sequence numbers 我
  • 尝试将 Asp.Net Memebership 数据库部署到 SQL Azure

    我一直在尝试让 ASP net 会员服务提供商与托管在 SQL Azure 中的其余数据库配合使用 我已针对数据库运行适当的 SQL Azure 特定脚本来进行设置 这些脚本可从 Microsoft 获取 http archive msdn
  • 在 64 位 OS X 10.6 上制作胖二进制文件更喜欢 32 位的正确方法?

    假设我问用户 你想在 32 位模式还是 64 位模式下运行 他们选择 32 位 我如何向操作系统注册这一事实 我看过arch http developer apple com mac library documentation Darwin
  • 为什么空闲的 SignalR 连接本地网络负载为 4-6 Mbps? [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我的启用 SignalR 的应用程序会产生较高的本地网络流量 但前提是在 Chrome 中运行并且该应用程序由 IIS Expre
  • Git 无效的修订范围 Symfony2 Composer 外部包

    RuntimeException Failed to execute git log 18efcf67d236d5bbf46ac67820250dffd0474b6e 94e2146f525fa1367e15646fa273e5b34f92
  • 在 Unix 中添加用户和组

    有谁知道在unix中添加用户和组以及删除它们的api吗 我想以编程方式执行此操作 谢谢 坦率 我开始查看一些系统调用并发现以下内容 请注意 它们具有不同的标准 因此并非所有标准都可以在您的 Unix 版本上运行 getpwent setpw
  • 将 FireBug 用于带有框架的网站

    我下载了 Firebug 并尝试使用它来调试使用框架的站点的 JS 我的理解是 当我进入 Firebug 中的 脚本 选项卡时 我会看到 aspx 上的 JS 函数以及包含的任何文件中的 JS 并且我将能够设置断点 然而 我在这个网站上看到
  • 在 WSL Ubuntu 20.04 上安装 npm 后,我收到消息“/usr/bin/env: ‘bash\r’: No such file or directory”

    运行时我看到以下消息npm install or npm来自终端的命令 执行中node按预期工作 gt npm install usr bin env bash r No such file or directory 2023 年 7 月更
  • 为什么该字符串的长度比其中的字符数长?

    这段代码 string a abc string b A C Console WriteLine Length a 0 a Length Console WriteLine Length b 0 b Length outputs Lengt
  • Caffe 的 LSTM 模块

    有谁知道 Caffe 是否有一个不错的 LSTM 模块 我从 russel91 的 github 帐户中找到了一个 但显然包含示例和解释的网页消失了 以前是http apollo deepmatter io http apollo deep
  • 应用洞察和服务结构?

    I found this https stackoverflow com questions 37348793 application insights in service fabric几个月前有关 Application Insight
  • 为什么拥有单独的投影矩阵但结合模型和视图矩阵会有好处?

    当您学习 3D 编程时 您会被告知用 3 个变换矩阵来思考是最简单的 模型矩阵 该矩阵对于每个模型都是独立的 它根据需要旋转和缩放对象 最后将其移动到 3D 世界中的最终位置 模型矩阵将模型坐标转换为世界坐标 视图矩阵 对于大量对象 如果不
  • 如何防止弹出表单夺走父级的焦点

    我有一个小的 windows form 当鼠标悬停在 windows Form 上的某个区域上时 我用它来显示信息 但是当它设置为可见时 它会从父窗口获取焦点 有没有办法防止这种情况 它会导致主窗体在焦点和焦点之间切换时闪烁 时间 2019
  • FreePascal x64 上系统单元函数的汇编调用

    我有一些 Delphi 汇编代码 可以在 Win32 Win64 和 OSX 32 上编译并正常工作 XE2 但是 由于我需要它在 Linux 上工作 所以我一直在考虑编译它的 FPC 版本 到目前为止 Win32 64 Linux32 6