Почему для использования xor вместо mov требуется меньше байтов? - PullRequest
1 голос
/ 25 сентября 2019

При установке x на ноль (x = 0) моя книга csapp указывает на два пути.

Первый:

xorq %rcx, %rcx

Второй:

movq $0, %rcx

Этотакже говорит, что первый занимает всего 3 байта, а второй занимает 7 байтов.

Как работают эти два способа?Почему первый занимает меньше байтов, чем второй?

Ответы [ 3 ]

5 голосов
/ 25 сентября 2019

Поскольку mov требуется больше места для кодирования его 32-разрядного непосредственного операнда источника.
xor нужен только байт ModRM для кодирования его операндов.

Ни один из нихнужен префикс REX, поэтому вы должны сравнивать 2-байтовый xor %ecx,%ecx с 5-байтовым mov $0, %ecx. Почему инструкции x86-64 для 32-битных регистров обнуляют верхнюю часть полного 64-битного регистра? GAS не выполняет эту оптимизацию для вас, а movq дает вам кодировку mov $sign_extended_imm32, %r/m64вместо особого случая 5-байтовой кодировки mov $imm32, %r32, которая пропускает байт ModRM.

(Как отмечено в В примере CS: APP используется idivq с двумя операндами? , кажется, что CS: APPбыть полными ошибок asm. Это не ошибка неверного синтаксиса, а просто пропущенная оптимизация.)


К сожалению, кодирование mov с 8-разрядным непосредственным расширением знака, к сожалению, отсутствует.иначе мы могли бы иметь 3 байта mov reg, imm8.(https://www.felixcloutier.com/x86/mov). (Я удивлен, что ни одна итерация x86-64 не переназначила один из байтов кода операции, который он высвободил для хорошей кодировки mov, подобной этой, возможно, смешанной с BMI1 или чем-то.)

Для получения более подробной информации о кодировке инструкций x86, прочитайте руководство Intel vol.2 и посмотрите разборку.

См. Также Какой лучший способ установить регистр в ноль в сборке x86: xor, movили и? для получения более подробной информации о том, почему обнуление xor оптимально: на некоторых процессорах, особенно семейства P6 и семейства Sandybridge, оно имеет микроархитектурные преимущества по сравнению с mov, помимо простого размера кода.

2 голосов
/ 25 сентября 2019

Почему первый занимает меньше байтов, чем второй?

Хотя ответ Питера Кордеса уже о технических деталях, я бы хотел сосредоточиться на математическом фоне:

x86s CPU, очевидно, не различает большие числа (например, 12345789) и нулевое значение: для хранения такого значения требуется 4 байта.

Однако нулевое значение является очень специальным значением:

Он может быть записан как (aa) или как (a XOR a), а «a» может быть любым целочисленным значением!

Это означает, что вы можете выполнить трюк:

Вы выполняете операцию subq %rcx, %rcx для вычисления значения (rcx - rcx).Неважно, какое значение имеет rcx: если вы вычтите это значение из себя, результат будет нулевым (потому что (aa) = 0).

Это означает, что rcx будет 0 после этогооперация.

Операция xorq %rcx, %rcx имеет тот же эффект, поскольку (XOR a) также всегда равно 0.

0 голосов
/ 29 сентября 2019

xorq %rcx, %rcx это означает rcx = 0 и movq $0, %rcx это означает rcx = 0

Оба имеют одинаковый эффект, но xor инструкция имеет меньшее значение

...