Ответ 1
mov %esi, %esi
выдает высокие 32 бита% rsi и поэтому не является no-op на x86_64.
Я немного смущен комментарием в одном из файлов заголовков для ядра Linux, arch/x86/include/asm/nops.h. В нем указано, что
<... > следующие инструкции НЕ являются nops в 64-битном режиме, для 64-битного режима используйте K8 или P6 nops вместо
movl% esi,% esi
leal 0x00 (% esi),% esi
<... >
Я предполагаю, что автор подразумевал машинные инструкции ('89 F6 'и' 8D 76 00 ', соответственно), а не инструкции сборки. Из описания LEA
в руководстве Intel Software Developer Manual Vol 2A следует, что последняя инструкция (lea 0x00(%rsi), %esi
) делает то же самое, что и первая, mov %esi,%esi
.
Итак, это сводится к вопросу, является ли mov %esi,%esi
фактически не-операцией на x86-64.
mov
не изменяет флаги. Этот тип mov
тоже не изменяет память. Кажется, если он что-то изменит, кроме %rip
, это должны быть регистры общего назначения. Но я не знаю, как это может изменить содержимое %rsi
или что-то еще. Если вы управляете нижней половиной регистра общего назначения, верхняя половина не должна изменяться, правильно?
mov %esi, %esi
выдает высокие 32 бита% rsi и поэтому не является no-op на x86_64.
#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;
}
Это дает "reg_rsi = 0x12345678" для моей машины x86_64.