Подтвердить что ты не робот

Как читать и писать регистры x86 флаги напрямую?

Из того, что я читал, кажется, что существует 9 разных флагов. Можно ли их напрямую читать/изменять? Я знаю, что знаю, например, если флаг нуля установлен после выполнения инструкции cmp/jmp, но я спрашиваю, можно ли сделать что-то вроде

mov eax, flags

или что-то в этом роде.

Также, для записи, можно ли их вручную установить?

4b9b3361

Ответ 1

Некоторые флаги могут быть установлены или удалены напрямую с помощью специальных инструкций:

  • CLC, STC и CMC: очистить, установить и дополнить флаг переноса
  • CLI и STI: очистить и установить флаг прерывания (что должно быть сделано атомарно)
  • CLD и STD: очистить и установить флаг направления

Для чтения и записи знаков, нуля, вспомогательных флагов переноса, контроля четности и переноса вы можете использовать LAHF для загрузки младших 8 битов (эти 5 флагов плюс 3 неопределенных бита) в регистр AH и использовать SAHF для их сохранения. значения из AH возвращаются в регистр флагов.

Вы также можете использовать инструкцию PUSHF, чтобы поместить флаги в стек, прочитать и изменить их в стеке, а затем использовать инструкцию POPF 1, чтобы сохранить их обратно в регистр флагов.

Обратите внимание, что вы не можете установить флаги VM и 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 также просты, с/без инвертирования флага.

Ответ 2

Вы можете использовать команды pushf и popf, которые будут вытолкнуть флаги в стек, вы можете их изменить и затем отбросить.

Ответ 3

Если вам нужен только младший байт регистра флагов (который содержит SF, ZF, AF, PF, CF), то есть нечетная, но удобная инструкция LAHF (ha ha), которая загружает нижние 8 бит флаги регистрируются в AH и его коллега SAHF для хранения AH во флагах.

Для флага переноса специально x86 предлагает CLC, STC и CMC, чтобы очистить, установить и дополнить флаг переноса, соответственно.

Ответ 4

Самый простой способ - использовать pushf/popf.

Если вы хотите переместить eflags в eax, используйте код ниже.

pushf                  # push eflags into stack
pop %eax               # pop it into %eax

Ответ 5

SETcc

Это семейство инструкций - еще один способ наблюдать некоторые флаги/комбинации флагов.

Он устанавливает значение байта на основе отдельных флагов.

Например, для CF:

stc
setc al
; al == 1

clc
setc al
; al == 0

Запускаемый GitHub upstream с утверждениями.

Jcc

Это семейство команд, конечно, является еще одной возможностью для определенных флагов и может использоваться для реализации SETcc:

jc set
mov al, 0
jmp end
set:
mov al, 1
end:

Запускаемый GitHub upstream с утверждениями.

Ответ 6

  • LAHF: загружает флаги состояния в AH
  • Копирует младший байт регистра EFLAGS, включая флаги Sign, Zero и Carry.
  • Сохраните копию флагов в переменной для сохранения

    .data
     saveflags BYTE ? 
    .code 
     lahf ; load flags into AH 
     mov saveflags,ah ; save them into a variable 
    
  • SAHF: сохраняет AH в флаги состояния

  • Копирует AH в младший байт регистра EFLAGS
  • Получить значение ранее сохраненных флагов

    .code
     mov ah, saveflags ; load save flags into AH 
     sahf ; copy into flags register