Asm相当于一个delphi程序
我有一个简单的delphi函数,名为SetCompare,它比较两个单值,如果它们不相等,则将一个值设置为另一个值Asm相当于一个delphi程序,delphi,assembly,x86-64,Delphi,Assembly,X86 64,我有一个简单的delphi函数,名为SetCompare,它比较两个单值,如果它们不相等,则将一个值设置为另一个值 procedure SetCompare( A : single; B : single ); begin if( A <> B ) then A := B; end; 这样行吗 这样行吗 不,这不起作用,因为浮点比较与二进制比较不同。例如,0和-0具有不同的位模式,但比较时相同。类似地,NaN比较不等于所有值,包括具有相同位模式的NaN
procedure SetCompare( A : single; B : single );
begin
if( A <> B ) then
A := B;
end;
这样行吗
这样行吗
不,这不起作用,因为浮点比较与二进制比较不同。例如,0
和-0
具有不同的位模式,但比较时相同。类似地,NaN
比较不等于所有值,包括具有相同位模式的NaN
解决如何编写代码的最简单方法是让编译器编译Pascal代码,并检查生成的汇编代码
一些旁白:
- 无论如何,您的函数是没有意义的,因为它不返回任何值,也没有副作用
- 如果性能对编写汇编程序非常重要,那么您应该编写纯汇编程序函数,而不是在Pascal函数中内联
块。在任何情况下,x64编译器都不支持该选项asm
- 您的参数已经存在于寄存器中,因此将它们复制到其他寄存器没有什么意义。对于x86代码,
到达A
,而EAX
到达B
。既然EDX
已经包含EAX
,为什么要将其复制到A
?它已经在那里了。而且EAX
已经在B
中,为什么要将其复制到EDX
?对于x64代码,这两个参数在浮点寄存器中传递,可以直接在那里进行比较。一旦开始编写汇编程序,您就需要了解调用约定的寄存器用法ECX
- 你的
毫无意义。如果执行没有跳转,那么它将移动到下一行代码。这就是你跳到的地方jne
var
参数。请获取或模拟的副本。为什么要转换为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)中工作。这一切都很好,但反汇编通常充满了类似于MOV EAX、[EBP-$08]
的代码,这些代码根本不容易阅读。要真正习惯这一点并能够阅读这样的代码需要一些时间。@RudyVelthuis和生活中的许多事情一样,需要知识和专业知识。的确如此。但我不认为查看生成的汇编代码对初学者有帮助。这可能会让人困惑。对于初学者来说,一切都会让人困惑。但并不是所有读这篇文章的人都是初学者。我知道我会研究一个或多个编译器发出的代码,然后在这个指导下做进一步的研究。我们的工作也不是教一个完全没有知识或经验的初学者写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;