Оптимизация ассемблера: удивительная роль команды XOR
В одном из моих докладов о языке ассемблера я представил список из 20 наиболее часто используемых команд для десктопов на архитектуре x86 с операционной системой Linux. Среди привычных инструкций, таких как mov, add и sub, неожиданно оказалась команда xor — «eXclusive OR». Это вызвало удивление, так как в моё время хакерства на 6502, XOR обычно указывал на шифрование или обработку спрайтов. Тем не менее, современные компиляторы активно используют эту команду для присвоения нулевого значения регистру, как это происходит в следующем примере: int main() { return 0; }.
При компиляции с оптимизацией -O2 и включении опции «Compile to binary object» я увидел, что команда xor eax, eax занимает всего два байта, в то время как mov eax, 0 занимает пять. Это позволяет экономить место в коде и улучшает кэширование. Более того, процессоры x86 оптимизируют выполнение xor, что делает его выполнение фактически бесплатным по времени.
Однако, почему команда xor eax, eax встречается чаще, чем xor rax, rax? Это связано с тем, что запись в регистры e-регистров автоматически обнуляет старшие 32 бита. Интересно, что для обнуления расширенных регистров, таких как r8, GCC использует 32-битный вариант, что также упрощает компиляцию. В итоге, использование xor не только уменьшает код, но и ускоряет его выполнение! Спасибо компиляторам!
