我对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
或其他内容。如果你操纵通用寄存器的下半部分,上半部分不应该改变,对吧?
答案 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”。