在%x86-64上,mov%esi,%esi是否为no-op?

时间:2011-07-11 17:38:31

标签: assembly linux-kernel x86-64

我对Linux内核的一个头文件arch/x86/include/asm/nops.h中的注释感到有些困惑。它说明了

  

< ...>以下指令在64位模式下不是nops,对于64位模式,使用K8或P6 nops代替   movl%esi,%esi
  leal 0x00(%esi),%esi
  < ...>

我猜作者暗示机器指令(分别为'89 F6'和'8D 76 00')而不是汇编指令。根据英特尔软件开发人员手册第2A卷中LEA的描述,后一条指令(lea 0x00(%rsi), %esi)与前者mov %esi,%esi的作用相同。

所以这就减少了问题,mov %esi,%esi在x86-64上是否实际上是无操作。

mov不会更改标记。这种mov也不会改变记忆。似乎,如果它改变%rip以外的东西,那应该是通用寄存器。但我不知道它如何改变%rsi或其他内容。如果你操纵通用寄存器的下半部分,上半部分不应该改变,对吧?

2 个答案:

答案 0 :(得分:17)

mov %esi, %esi

将%rsi的高32位归零,因此不是x86_64上的无操作。

答案 1 :(得分:6)

#include <stdio.h>

int main(int argc, char * argv[])
{
    void * reg_rsi = 0;

    asm (
        "movq $0x1234567812345678, %%rsi;\n"
        "movl %%esi, %%esi;\n"
        "movq %%rsi, %0;\n"
        : "=r" (reg_rsi)
        : /* no inputs */
        : /* no clobbered */
    );

    printf("reg_rsi = %p\n", reg_rsi);

    return 0;
}

这为我的x86_64机器提供了“reg_rsi = 0x12345678”。