【问题标题】:Asm equivalent to a delphi procedureasm相当于一个delphi程序
【发布时间】:2017-09-16 18:36:31
【问题描述】:

我有一个名为 SetCompare 的简单 delphi 函数,它比较两个单曲,如果它们不相等,则将一个值设置为另一个。

procedure SetCompare( A : single; B : single );
  begin
    if( A <> B ) then
      A := B;
  end;

我正在尝试将其转换为 asm:

procedure SetCompare( A : Single; B : Single ); register;
  begin
    asm
      mov EAX,A
      mov ECX,B
      cmp EAX,ECX
      jne SetValue

      @SetValue:
      mov EAX,ECX
    end;
  end;

这行得通吗?

【问题讨论】:

  • 这样做的目的是什么?你测试过你的代码吗?有效吗?
  • 程序 != 函数。您的任何代码都没有任何意义。另请注意,此处的参数是按值传递的(即传递了一个副本)。您对参数所做的任何更改都不会离开程序。如果您希望这种情况发生,您需要有var 参数。请获取marcocantu.com/objectpascalhandbook 或类似的副本。
  • 为什么要转asm?这是糟糕的 Delphi 代码(即使你修复了错误),而且在 asm 中会更糟!退一步想想你在做什么:1)如果A和B不同:你做一个比较和一个分配。 2)如果A和B相同:您进行比较和跳转。 即两种情况下都有 2 次操作 但是如果你想让 A 和 B 一样,那么简单地分配 A := B; 是一个单个操作。因此,您的方法不会获得任何性能优势 - 由于您没有考虑到浮点的细微差别,您只会产生意外行为的可能性。
  • 老实说,如果您将其中一个设置为与另一个不相同的情况下相等,那么始终将 A 设置为 B 不是更容易吗?
  • 在跨平台语言中使用 asm 是个坏主意。因为这个 asm 部分只能在 x86 上工作,在 x64、Android (ARM)、MacOS (x64) 和 iOS (ARM) 上都不能工作。

标签: delphi assembly x86-64


【解决方案1】:

这行得通吗?

不,这不起作用,因为浮点比较与二进制比较不同。例如0 和-0 具有不同的位模式,但比较相等。同样,NaN 比较不等于所有值,包括具有相同位模式的NaN。

弄清楚如何编写代码的最简单方法是让编译器编译 Pascal 代码,并检查生成的汇编代码。

一些旁白:

  • 无论如何,您的函数毫无意义,因为它没有返回值并且没有副作用。
  • 如果性能对编写汇编程序足够重要,那么您应该编写纯汇编程序函数,而不是在 Pascal 函数中内联 asm 块。在任何情况下 x64 编译器都不支持。
  • 您的参数已经在寄存器中,因此将它们复制到其他寄存器几乎没有意义。对于 x86 代码,A 到达 EAX,B 到达 EDX。鉴于EAX 已经包含A,为什么要将它复制到EAX 中?它已经在那里了。而B 已经在EDX 中,为什么要复制到ECX 中呢?对于 x64 代码,这两个参数在浮点寄存器中传递,并且可以在那里直接进行比较。一旦开始编写汇编程序,您就需要了解调用约定的寄存器用法。
  • 您的jne 毫无意义。如果执行没有跳转,那么它会移动到下一行代码。你跳到哪了。

【讨论】:

  • 一切都很好,但是反汇编通常充满了像MOV EAX,[EBP-$08]这样的代码,根本不容易阅读。真正习惯这一点并能够阅读这样的代码需要一些时间。
  • @RudyVelthuis 就像生活中的许多事情一样,需要知识和专业知识。
  • 确实如此。但我不认为查看生成的汇编代码对初学者有帮助。这可能甚至令人困惑。
  • 一切都会让初学者感到困惑。但并非所有阅读本文的人都是初学者。我知道我会研究一个或多个编译器发出的代码,然后在此指导下进行进一步的研究。教一个没有编写 asm 知识或经验的完整初学者也不是我们的工作,如何做到这一点。这太过分了。
猜你喜欢
  • 2015-08-23
  • 2011-02-04
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多