какая польза от переноса регистра в себя в x86-64 - PullRequest
4 голосов
/ 14 марта 2019

Я делаю проект в NASM x86-64 и наткнулся на инструкцию:

mov rdi, rdi

в выводе компилятора, который написал мой профессор.

Я искал по всемуно не могу найти упоминания о том, зачем это нужно.Влияет ли это на флаги или это что-то умное, чего я не понимаю?

Чтобы придать некоторый контекст, он присутствует в цикле непосредственно перед тем, как тот же регистр уменьшен с sub.

1 Ответ

7 голосов
/ 14 марта 2019

Инструкция mov rdi, rdi является просто неэффективной 3-байтовой NOP, эквивалентной действительной инструкции NOP. Собрав его, он генерирует байтовую комбинацию

48 89 ff       mov rdi, rdi

Это можно рассматривать как NOP, поскольку оно не влияет ни на флаги, ни на регистры. Единственный архитектурный эффект - продвижение счетчика программы к следующей инструкции.

Обычно используется (многобайтовый) NOP s для выравнивания следующей инструкции по определенному адресу, популярным примером является выровненная цель перехода, особенно в верхней части цикла.

Но в данном случае кажется, что это просто артефакт генерации кода из неоптимизирующего компилятора, не используется для преднамеренного заполнения.


Это неэффективно по сравнению с истинным nop, потому что это не будет специальным случаем, чтобы бежать дешевле. (Его архитектурный эффект микро отличается на современных процессорах). Он добавляет цикл задержки в цепочку зависимостей через RDI и использует исполнительный модуль ALU. (Ни процессоры Intel, ни AMD не могут «исключить» mov same,same и запустить его с нулевой задержкой на этапе переименования регистров, только между различными архитектурными регистрами. Например, mov rax,rdi может стоить примерно столько же, сколько nop на IvyBridge + и Райзен, если не возражаешь насчет RAX.)

В вашем случае вы должны просто удалить его (вместо замены на 66 66 90 (короткий NOP с избыточными префиксами размера операнда) или 01 1F 00 (длинный NOP), потому что он не используется для заполнения.

...