Оптимизация кода: загадка команды XOR

В одном из своих докладов по ассемблеру я представил список из 20 наиболее часто выполняемых команд на десктопе с x86 и Linux. В этом списке, помимо привычных команд, таких как mov, add и jmp, неожиданным образом оказалась команда xor. В прошлом, когда я занимался хакингом на 6502, наличие XOR сигнализировало о том, что код может быть связан с шифрованием или обработкой спрайтов. Интересно, что на Linux эта команда также активно используется.

Компиляторы часто генерируют xor для присвоения нулевого значения регистру. Например, в случае кода int main() { return 0; } команда xor eax, eax занимает всего 2 байта, в то время как mov eax, 0 требует 5 байт. Это позволяет экономить пространство и повышать эффективность использования кэша команд.

Кроме того, процессоры x86 оптимизируют выполнение этой команды, благодаря чему xor может исполняться без затрат тактов, что делает её ещё более привлекательной для компиляторов.

При записи в регистр rax, например, для функции long get_zero_long() { return 0; }, использование команды xor eax, eax обнуляет все 64 бита благодаря особенностям архитектуры.

Важно отметить, что при обнулении расширенных регистров, таких как r8, компиляторы также используют 32-битный вариант, что упрощает процесс. Таким образом, использование xor eax, eax позволяет не только сократить размер кода, но и ускорить его выполнение.