Gcc mov%rax,%rax的用途是什么?

Gcc mov%rax,%rax的用途是什么?,gcc,assembly,Gcc,Assembly,我目前正在通过反汇编一些C代码来学习ASM。我感兴趣的一件事是gcc编译器生成如下代码 movq %rax,%rax 这显然毫无意义。那么这样做的目的是什么呢 我想知道它是否用于浪费几个CPU周期,以改善管道 谢谢你的提示 这基本上是一个不可操作的问题,是的 编译器之所以这样做,是因为分支到4字节边界上对齐的地址比分支到未对齐的地址要快。因此,如果您有一个循环,编译器将在循环开始之前插入“padding”,以使其对齐。看起来是一个合理的解释。但是为什么不使用NOP指令呢?x86没有“专用”NO

我目前正在通过反汇编一些C代码来学习ASM。我感兴趣的一件事是gcc编译器生成如下代码

movq %rax,%rax
这显然毫无意义。那么这样做的目的是什么呢

我想知道它是否用于浪费几个CPU周期,以改善管道


谢谢你的提示

这基本上是一个不可操作的问题,是的


编译器之所以这样做,是因为分支到4字节边界上对齐的地址比分支到未对齐的地址要快。因此,如果您有一个循环,编译器将在循环开始之前插入“padding”,以使其对齐。

看起来是一个合理的解释。但是为什么不使用NOP指令呢?x86没有“专用”NOP指令。1字节NOP指令的确切操作码为
xchg%eax,%eax
,对于其他NOP大小也是如此。编译器根据所需的填充量选择大小合适的no op。因为标准NOP指令的长度为1字节,而编译器需要2字节进行填充。1条指令比2条指令快,即使两条指令都是NOP。例如,常见的3字节NOP是
lea edi,[edi+0]
实际上,操作码0x90(对应于32位代码中的
xchg%eax,%eax
)是x86-64上的专用NOP。如果对任何其他32位寄存器执行此操作,它将清除相应64位寄存器的前32位,但不会以“eax,eax”形式清除。它不用于改进管道。所有x86处理器(出于历史原因?)都有硬件,可在必要时通过暂停来解决此类危险。只有更简单的RISC才需要编译器支持。@ruslik:暂停本身就是一种危险。