Потому что 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 полно ассемблерных ошибок. Это не недопустимая синтаксическая ошибка, а просто пропущенная оптимизация.)
К сожалению, нет кодирования mov
с 8-битным непосредственным расширением знака, иначе мы могли бы иметь 3-байтовое mov reg, imm8
. (https://www.felixcloutier.com/x86/mov). (Я удивлен, что никакая итерация x86-64 не переназначила один из байтов кода операции, который он освободил, для такой хорошей кодировки mov
, возможно, смешанной с BMI1 или чем-то еще.)
Для получения более подробной информации о кодировании инструкций x86 прочитайте руководство Intel vol.2 и посмотрите на дизассемблирование.
См. также Как лучше всего обнулить регистр в ассемблере x86: xor, mov или and? подробнее о том, почему xor-zeroing оптимален: на некоторых процессорах, особенно в семействе P6 и Sandybridge-family, он имеет микроархитектурные преимущества перед mov
помимо просто размера кода.
person
Peter Cordes
schedule
25.09.2019
xor %eax, %eax
еще короче — всего два байта. - person fuz   schedule 25.09.2019