Assembly 在内存位置上调用'add'是否比在寄存器上调用它然后移动值更快?

Assembly 在内存位置上调用'add'是否比在寄存器上调用它然后移动值更快?,assembly,x86,x86-64,micro-optimization,Assembly,X86,X86 64,Micro Optimization,更快的是: add DWORD PTR [rbp-0x4],1 或 我见过编译器生成的第二个代码,因此在寄存器上调用add可能要快得多?添加到寄存器可能要快得多(因为寄存器是片上的),但是,由于无论如何都必须加载和存储数据,所以不太可能看到改进 冗长的方法甚至可能更慢,因为CPU可能有机会优化较短的代码。此外,较短的代码可能具有读/修改/写的原子性,这取决于您如何编写代码。它当然不会浪费eax寄存器 总之,较长的代码不太可能有足够的改进(如果有的话)来证明其可读性 但你不必猜测(甚至不必问我们

更快的是:

add DWORD PTR [rbp-0x4],1


我见过编译器生成的第二个代码,因此在寄存器上调用
add
可能要快得多?

添加到寄存器可能要快得多(因为寄存器是片上的),但是,由于无论如何都必须加载和存储数据,所以不太可能看到改进

冗长的方法甚至可能更慢,因为CPU可能有机会优化较短的代码。此外,较短的代码可能具有读/修改/写的原子性,这取决于您如何编写代码。它当然不会浪费
eax
寄存器

总之,较长的代码不太可能有足够的改进(如果有的话)来证明其可读性


但你不必猜测(甚至不必问我们)——芯片制造商提供了大量关于指令时间安排的详细信息。例如,.

它们都解码为相同数量的后端UOP,但内存目标
add
通过前端在现代Intel/AMD CPU上较少的融合域UOP中获取这些UOP

在英特尔CPU上,
add[mem],imm
解码为微融合加载+添加和微融合存储地址+存储数据,因此前端总共有2个融合域UOP。AMD CPU总是将内存操作数与ALU操作分组,而不称之为“微融合”,这正是它们一直以来的工作方式。 (和)


第一种方法不会将值保留在寄存器中,因此如果使用了表达式的值,则不能将其用作
++a
的一部分。仅用于治疗对记忆的副作用


使用
[rbp-4]
并递增内存中的本地代码闻起来像是未优化/调试模式代码,您不应该查看它的效率。
优化代码通常使用
[rsp+-constant]
来处理本地代码,并且(除非变量是
volatile
)不会马上把它重新存储到内存中

-在调试模式下编译,aka
-O0
(默认值)分别编译每个C语句,并将每个变量视为
volatile
,这非常可怕


有关如何让编译器生成有趣的asm的信息,请参阅。编写一个函数,该函数接受args并返回一个值,这样它就可以执行某些操作,而无需优化掉常量或将常量传播到
mov eax,常量结果

可能较慢,但实现已定义…您可能看到它是由禁用优化的编译器生成的…Re:atomicity:仅针对中断,因此仅wrt。在该内核上运行的其他代码。在C++中,我们可以说它是原子WRT。同一线程中的一个信号处理程序。@Peter,这就是为什么我使用了黄鼠狼的话“取决于您如何编码”:-)我的理解是,内存上的
inc
操作码上的
lock
前缀将被buslock锁定,以便其他内核不会尝试使用该值。我可能是错的,当然,我已经有一段时间没有在金属附近编码了。对,让它成为原子wrt。您需要的其他内核
lock inc[mem]
lock add[mem],1
。但是,如果内存没有跨缓存线拆分,那么内核只需要保留从加载到存储的那一行(一个“缓存锁”)的MESI独占所有权;无需打扰正在访问不同线路的其他内核。有详细的概述。感谢您的详细回答。
 mov    eax,DWORD PTR [rbp-0x4]
 add    eax,1
 mov    DWORD PTR [rbp-0x4],eax