mov%esi,%esi是x86-64上的无操作吗?

问题描述 投票:8回答:2

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

<...>以下说明在64位模式下不是nop,对于64位模式,请使用K8或P6 nopsmovl%esi,%esileal 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的内容。如果您操纵通用寄存器的下半部分,那么上半部分应该不会改变,对吧?

assembly linux-kernel x86-64
2个回答
19
投票
mov %esi, %esi

将%rsi的高32位清零,因此在x86_64上不是空操作。

请参见Why do x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register?


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”。

© www.soinside.com 2019 - 2024. All rights reserved.