Для каждой инструкции задокументировано, записывает ли (и как) EFLAGS . Справочное руководство по набору инструкций Intel содержит раздел «Затронутые флаги» в каждой инструкции. Для некоторых это просто Нет.
http://ref.x86asm.net/coder32.html имеет удобную таблицу инструкций, включающую столбец, показывающий, какие флаги они читают и изменяют, а какие из модифицированных флагов четко определены и не определены. (Нажмите на заголовки столбцов для описания).
Большинство целочисленных инструкций ALU, таких как sub
и add
, обновляют флаги «в соответствии с результатом»;это то место, где применяются общие описания, такие как установка SF = старший бит. Такие инструкции, как cmp
и test
только дают результат FLAGS, не изменяя ни одно целочисленное значение.
lea
и not
являются известными исключениями ALU, которые не устанавливают флаги. Инструкции перемещения данных не устанавливают флаги, такие как mov
и push
/ pop
. например, Flags Acted: None.
inc
/ dec
установить флаги, кроме CF, которые они оставляют неизмененными. ( Большинство процессоров все еще могут эффективно это обрабатывать )
Инструкции SSE и fp, такие как addsd xmm, xmm/mem
, обычно не пишут флаги. Вы можете выполнить сравнение FP в EFLAGS на современном x86 с comisd xmm, xmm/mem
(SSE2) или fcomi st?
(x87 + Pentium Pro).
Некоторые примеры из руководства Intel vol.2:
Инструкции, которые пишут флаги «интересными» способами, часто также определяют это в псевдокоде раздела «операции». например, bsf
add
: Затронутые флаги
OF, SF, ZF, AF, CF и PFФлаги устанавливаются в соответствии с результатом.
(Если вы посмотрите PDF-файл руководства Intel для vol.2, или, возможно, vol.1, я думаю, что они точно определяют, что означает «в соответствии с результатом».)
imul
: Затрагиваемые флаги:
Для формы команды с одним операндом, флагов CF и OFустанавливаются, когда значащие биты переносятся в верхнюю половину результата, и очищаются, когда результат точно соответствует нижней половине результата. Для форм команды с двумя и тремя операндами флаги CF и OF устанавливаются, когда результат должен быть усечен, чтобы соответствовать размеру операнда назначения, и очищаются, когда результат точно соответствует размеру операнда назначения. Флаги SF, ZF, AF и PF не определены.
sar
/ shl
/ shr
Затронутые флаги:
Флаг CF содержит значение последнего бита, сдвинутого из операнда назначения;он не определен для команд SHL и SHR, где число больше или равно размеру (в битах) операнда назначения. На флаг OF влияют только сдвиги в 1 бит (см. «Описание» выше);в противном случае он не определен. Флаги SF, ZF и PF устанавливаются в соответствии с результатом. Если счетчик равен 0, флаги не затрагиваются . Для ненулевого счета флаг AF не определен.
Оставить флаги неизмененными для count = 0 - еще одна сумасшедшая лазейка CISC для высокопроизводительных реализаций. (Часть «налога x86», которую должна уплатить микроархитектура для правильной реализации семантики x86). В семействе Intel Sandybridge это означает, что сдвиги с переменным числом (с количеством в cl
) декодируют до 3 моп. SHLX (сдвиги без флагов BMI2) - всего 1 моп.
Еще один способ ответить на вопрос «как часто»: до 4 раз за такт . Или 5 на дзен или ледяное озеро. (Не более одного раза на инструкцию.)
Современные процессоры Intel имеют суперскалярную ширину 4. Они могут переименовывать EFLAGS 4 раза за один и тот же тактовый цикл, что позволяет им выполнять 4 независимых add reg,reg
инструкции за тактовый цикл, каждая из которых записывает результат своего флага в логический регистр EFLAGS, но на самом деле это другой физический регистр. (И действительно в сочетании с выводом EFLAGS в физическом регистре, содержащем целочисленный результат, за исключением инструкций типа cmp
, которые не имеют целочисленного результата.)
См. https://agner.org/optimize/