Вся справа в конвеєрі інструкцій . Пам’ятайте, сучасні центральні процесори виконують свої інструкції в конвеєрі, що дає значне підвищення продуктивності, коли процес виконання передбачуваний процесором.
cmov
add eax, ebx
cmp eax, 0x10
cmovne ebx, ecx
add eax, ecx
На даний момент, коли оцінюється ця інструкція ASM, результат попередньої інструкції CMP поки не відомий.
Можливо, але процесор все ще знає, що інструкція, що слідує за, cmov
буде виконана відразу після, незалежно від результату cmp
та cmov
інструкції. Таким чином, наступну інструкцію можна безпечно отримати / декодувати заздалегідь, що не стосується гілок.
Наступну інструкцію можна навіть виконати перед цим cmov
(у моєму прикладі це було б безпечно)
відділення
add eax, ebx
cmp eax, 0x10
je .skip
mov ebx, ecx
.skip:
add eax, ecx
У цьому випадку, коли декодер процесора побачить, je .skip
йому доведеться вибрати, чи продовжувати попереднє отримання / декодування інструкцій або 1) з наступної інструкції, або 2) з цілі переходу. Процесор здогадається, що цієї умовної гілки не відбудеться, тому наступна інструкція mov ebx, ecx
піде в конвеєр.
Через пару циклів je .skip
виконується і береться гілка. Ось лайно! Зараз наш конвеєр містить кілька випадкових сміття, які ніколи не слід виконувати. Процесор повинен очистити всі кешовані інструкції і почати все з самого початку .skip:
.
Це покарання за продуктивність неправильно передбачених гілок, чого ніколи не може статися, cmov
оскільки це не змінює потік виконання.