См. этот ответ для лучших регистров нуля: xor eax,eax
(преимущества в производительности и меньшая кодировка).
Я будуРассмотрим только способы, которыми одна инструкция может обнулить регистр.Существует слишком много способов, если вы разрешите загрузку нуля из памяти, поэтому мы в основном исключим инструкции, загружаемые из памяти.
Я нашел 10 различных отдельных инструкций, которые обнуляют 32-битный регистр (и, следовательно,полный 64-битный регистр в длинном режиме), без предварительных условий или загрузок из любой другой памяти.Это не считая разных кодировок одного и того же insn или разных форм mov
.Если вы посчитаете загрузку из памяти, которая, как известно, содержит ноль, или из регистров сегментов или чего-то еще, есть множество способов.Существует также миллиард способов обнуления векторных регистров.
Для большинства из них версии eax и rax являются отдельными кодировками для одной и той же функциональности, обе обнуляют полные 64-битные регистры, либо обнуляетверхняя половина неявно или явная запись полного регистра с префиксом REX.W.
Целочисленные регистры:
# Works on any reg unless noted, usually of any size. eax/ax/al as placeholders
and eax, 0 ; three encodings: imm8, imm32, and eax-only imm32
andn eax, eax,eax ; BMI1 instruction set: dest = ~s1 & s2
imul eax, any,0 ; eax = something * 0. two encodings: imm8, imm32
lea eax, [0] ; absolute encoding (disp32 with no base or index). Use [abs 0] in NASM if you used DEFAULT REL
lea eax, [rel 0] ; YASM supports this, but NASM doesn't: use a RIP-relative encoding to address a specific absolute address, making position-dependent code
mov eax, 0 ; 5 bytes to encode (B8 imm32)
mov rax, strict dword 0 ; 7 bytes: REX mov r/m64, sign-extended-imm32. NASM optimizes mov rax,0 to the 5B version, but dword or strict dword stops it for some reason
mov rax, strict qword 0 ; 10 bytes to encode (REX B8 imm64). movabs mnemonic for AT&T. normally assemblers choose smaller encodings if the operand fits, but strict qword forces the imm64.
sub eax, eax ; recognized as a zeroing idiom on some but maybe not all CPUs
xor eax, eax ; Preferred idiom: recognized on all CPUs
@movzx:
movzx eax, byte ptr[@movzx + 6] //Because the last byte of this instruction is 0. neat hack from GJ.'s answer
.l: loop .l ; clears e/rcx... eventually. from I. J. Kennedy's answer. To operate on only ECX, use an address-size prefix.
; rep lodsb ; not counted because it's not safe (potential segfaults), but also zeros ecx
«Переместить все биты на один конец» невозможнодля регистров GP обычного размера, только частичные регистры.Сдвиги shl
и shr
маскируются: count &= 31;
, что эквивалентно count %= 32;
.(Но 286 и более ранние версии - только 16-битные, поэтому ax
является «полным» регистром. Форма инструкции с переменным числом shr r/m16, imm8
была добавлена 286, поэтому были ЦП, где сдвиг может обнулять регистр полного целого числа.)
Также обратите внимание, что смещение для векторов имеет значение насыщения вместо переноса.
# Zeroing methods that only work on 16bit or 8bit regs:
shl ax, 16 ; shift count is still masked to 0x1F for any operand size less than 64b. i.e. count %= 32
shr al, 16 ; so 8b and 16b shifts can zero registers.
# zeroing ah/bh/ch/dh: Low byte of the reg = whatever garbage was in the high16 reg
movxz eax, ah ; From Jerry Coffin's answer
В зависимости от других существующих условий (кроме нуля в другом регистре):
bextr eax, any, eax ; if al >= 32, or ah = 0. BMI1
BLSR eax, src ; if src only has one set bit
CDQ ; edx = sign-extend(eax)
sbb eax, eax ; if CF=0. (Only recognized on AMD CPUs as dependent only on flags (not eax))
setcc al ; with a condition that will produce a zero based on known state of flags
PSHUFB xmm0, all-ones ; xmm0 bytes are cleared when the mask bytes have their high bit set
векторные регистры:
Некоторые из этих целочисленных инструкций SSE2 также могут использоваться в регистрах MMX (mm0
- mm7
).Опять же, лучший выбор - это некоторая форма xor.PXOR
/ VPXOR
или XORPS
/ VXORPS
.
AVX vxorps xmm0,xmm0,xmm0
обнуляет полный ymm0 / zmm0 и на лучше vxorps ymm0,ymm0,ymm0
на процессорах AMD .Эти инструкции обнуления имеют три кодировки: устаревшие SSE, AVX (префикс VEX) и AVX512 (префикс EVEX), хотя версия SSE обнуляет только нижние 128, что не является полным регистром на процессорах, которые поддерживают AVX или AVX512.В любом случае, в зависимости от того, как вы считаете, у каждой записи могут быть три разные инструкции (хотя один и тот же код операции, просто разные префиксы).За исключением vzeroall
, который AVX512 не изменил (и не обнуляет zmm16-31).
ANDNPD xmm0, xmm0
ANDNPS xmm0, xmm0
PANDN xmm0, xmm0 ; dest = ~dest & src
PCMPGTB xmm0, xmm0 ; n > n is always false.
PCMPGTW xmm0, xmm0 ; similarly, pcmpeqd is a good way to do _mm_set1_epi32(-1)
PCMPGTD xmm0, xmm0
PCMPGTQ xmm0, xmm0 ; SSE4.2, and slower than byte/word/dword
PSADBW xmm0, xmm0 ; sum of absolute differences
MPSADBW xmm0, xmm0, 0 ; SSE4.1. sum of absolute differences, register against itself with no offset. (imm8=0: same as PSADBW)
; shift-counts saturate and zero the reg, unlike for GP-register shifts
PSLLDQ xmm0, 16 ; left-shift the bytes in xmm0
PSRLDQ xmm0, 16 ; right-shift the bytes in xmm0
PSLLW xmm0, 16 ; left-shift the bits in each word
PSLLD xmm0, 32 ; double-word
PSLLQ xmm0, 64 ; quad-word
PSRLW/PSRLD/PSRLQ ; same but right shift
PSUBB/W/D/Q xmm0, xmm0 ; subtract packed elements, byte/word/dword/qword
PSUBSB/W xmm0, xmm0 ; sub with signed saturation
PSUBUSB/W xmm0, xmm0 ; sub with unsigned saturation
PXOR xmm0, xmm0
XORPD xmm0, xmm0
XORPS xmm0, xmm0
VZEROALL
# Can raise an exception on SNaN, so only usable if you know exceptions are masked
CMPLTPD xmm0, xmm0 # exception on QNaN or SNaN, or denormal
VCMPLT_OQPD xmm0, xmm0,xmm0 # exception only on SNaN or denormal
CMPLT_OQPS ditto
VCMPFALSE_OQPD xmm0, xmm0, xmm0 # This is really just another imm8 predicate value fro the same VCMPPD xmm,xmm,xmm, imm8 instruction. Same exception behaviour as LT_OQ.
SUBPS xmm0, xmm0
и т.п. не будет работать, потому что NaN-NaN = NaN, а не ноль.
Кроме того, инструкции FP могут вызывать исключения для аргументов NaN, поэтому даже CMPPS / PD безопасен только в том случае, если вы знаете, что исключения замаскированы, и вам не нужно устанавливать биты исключений в MXCSR.Даже версия AVX с расширенным выбором предикатов повысит #IA
на SNaN.«Тихие» предикаты только подавляют #IA
для QNaN.CMPPS / PD также может вызвать исключение Denormal.
(см. Таблицу в записи набора настроек insn для CMPPD или, предпочтительно, в исходном PDF-файле Intel, поскольку извлечение HTML портит эту таблицу.)
AVX512:
Возможно, здесь есть несколько вариантов, но мне сейчас не интересно, чтобы копаться в списке наборов инструкций и искать их все.
Однако стоит упомянуть один интересный: VPTERNLOGD / Q может вместо этого установить регистр в all-one , с imm8 = 0xFF.(Но имеет ложную зависимость от старого значения, от текущих реализаций).Поскольку все инструкции сравнения сравниваются в маске, VPTERNLOGD, по-видимому, является лучшим способом установить вектор для всех единиц на Skylake-AVX512 в моем тестировании, хотя это не является специальным случаем, в котором случай imm8 = 0xFFизбежать ложной зависимости .
VPTERNLOGD zmm0, zmm0,zmm0, 0 ; inputs can be any registers you like.
x87 FP:
Только один выбор (потому что sub не работает, если старое значение было бесконечностью или NaN).
FLDZ ; push +0.0