我有一个庞大的函数可以对大量的int
数据进行排序。代码工作正常,除了它应该更慢的事实。解决此问题的第一步是在asm
内放置一些C++
代码。如何使用asm
交换2个变量?我试过这个:
_asm{ push a[x]; push a[y]; pop a[x]; pop a[y];}
和此:
_asm(mov eax, a[x];mov ebx,a[y]; mov a[x],ebx; mov a[y],eax;}
但都崩溃了。如何在这些交汇处节省一些时间?我用的是VS_2010
答案 0 :(得分:4)
一般来说,使用像这样的简单代码来编译比编译器更难。
编译器在面对整数的交换操作时,通常会发出如下代码:
mov eax, [x]
mov ebx, [y]
mov [x], ebx
mov [y], eax
在尝试覆盖之前,首先检查编译器实际生成的内容。如果它是这样的话,不要再费心了;你将无法做到这一点。此外,如果将其留给编译器,如果此后立即使用这些变量,则可以选择重复使用其中一个寄存器来保存变量加载/存储。手动编码装配是不可能的;编译器必须在手动编码为asm的黑盒后重新加载变量。
请注意,推/推/弹出/弹出序列可能要慢得多;它不仅向堆栈添加了额外的四个内存操作,还引入了堆栈指针的依赖性,消除了任何流水线操作的可能性。使用简单的mov
序列,如果它们位于不同的存储体上,或者一个存储在缓存中,则至少可以并行运行读取和写入对。它也不会引入停顿。稍后代码中的堆栈指针。
因此,您不应试图微观优化交换的成本;相反,减少执行的交换次数。有许多sorting algorithms可用,每个都有不同的特征。您可能会发现数据集上的某些更好(导致交换更少)。
答案 1 :(得分:2)
是什么让你认为你可以比优化编译器产生更快的装配? 即使你能让它正常工作,你所有可能实现的就是混淆优化器以产生更慢的代码。
答案 2 :(得分:1)
您可以使用汇编代码中的变量名称,函数名称和标签作为符号。请注意,a[x]
之类的内容并非此类有效符号。
编写更高效的代码需要技巧和知识,使用asm并不一定能帮助你。
您可以比较编译器为内联汇编程序生成的函数的汇编代码,而不是查看您在哪里破解它。
答案 3 :(得分:1)
当您进行内联汇编时,您可以更改内容,以便编译器对寄存器内容所做的假设将不再成立。通常EAX用于传递参数或返回值,因此废弃EAX可能没有太大影响,但是你破坏了EBX并且没有将其放回去,这可能会导致问题。在使用之前尝试按EBX,然后在完成后弹出它。