Некоторые флаги могут быть установлены или удалены напрямую с помощью специальных инструкций:
- CLC , STC и CMC : сбросить, установить и дополнить флаг переноса
- CLI и STI : очистить и установить флаг прерывания (что должно быть сделано атомарно)
- CLD и STD : очистить и установить флаг направления
Для чтения и записи флагов знака, нуля, вспомогательного переноса, контроля четности и переноса вы можете использовать LAHF , чтобы загрузить младшие 8 бит (эти 5 флагов плюс 3 неопределенных бита) в регистр AH и вы можете использовать SAHF для сохранения этих значений из AH обратно в регистр флагов.
Вы также можете использовать инструкцию PUSHF , чтобы поместить флаги в стек, прочитать и изменить их в стеке, а затем использовать POPF 1 инструкция по сохранению их обратно в регистр флагов.
Обратите внимание, что вы не можете установить флаги ВМ и RF с помощью POPF - они сохраняют свои прежние значения. Точно так же вы можете изменять уровень привилегий ввода-вывода только при выполнении на уровне привилегий 0, а флаг прерывания можно изменять только при выполнении на уровне привилегий, по крайней мере с такими же привилегиями, как уровень привилегий ввода-вывода.
Сноска 1:
Обратите внимание, что popf
довольно медленно на современных процессорах; см. Руководство по оптимизации и инструкции Agner Fog . Он микрокодирован, потому что в режиме ядра он может изменять IF и AC, а также уровень привилегий IO. Мы страдаем от штрафа независимо от режима на текущих процессорах, потому что декодеры не чувствительны к режиму.
Если возможно, используйте lahf / sahf вместо pushf / popf для производительности или сохраните один интересующий вас флаг, например setc al
, а затем add al, 255
, чтобы установить CF = (AL!=0)
. Или setnc al
/ sub al, 1
или что-то еще. Последовательности установки или сброса SF или OF на основе регистра 0 или 1 также просты, с / без инвертирования флага.