Как установить/очистить флаг TF на процессоре Intel x86 IA32 в пользовательском режиме

Я хотел бы знать, как установить/очистить EFLAGS.TF в пользовательском режиме на процессоре Intel x86 IA32.

попробовал ниже для очистки флага TF, но получил ошибку ***** Unhandled interrupt vector *****

__asm__ volatile("pushl %eax\n\t"
                        "pushfl\n\t"
                        "popl %eax\n\t"
                        "xorl $0x0100, %eax\n\t"
                        "pushl %eax\n\t"
                        "popfl\n\t"
                        "popl %eax\n\t");

person richejose    schedule 19.07.2018    source источник
comment
Для очистки вам нужно либо убедиться, что он установлен, либо использовать ИЛИ для версии вашей битовой маски с НЕТ.   -  person wizzwizz4    schedule 19.07.2018
comment
Спасибо, WIZZ, изначально я пробовал и как показано ниже   -  person richejose    schedule 19.07.2018
comment
спасибо вам WIZZ изначально я пытался с и как показано ниже, это не работало и $0xFEFF, %eax\n\t; Но для EFlags нам нужно использовать andl correct, в этом случае ниже может быть правильным, я думаю, пожалуйста, поправьте меня, если я ошибаюсь andl $0xFFFFFEFF, %eax; С этим изменением я не получаю исключения, спасибо.   -  person richejose    schedule 19.07.2018
comment
Ты прав; Я не знаю, почему я предложил использовать ИЛИ... Это помогло бы многим другим людям, если бы вы опубликовали это как ответ (поле для ответа находится ниже); таким образом, в следующий раз, когда кто-то столкнется с этой проблемой, он найдет этот вопрос и немедленно получит ответ.   -  person wizzwizz4    schedule 19.07.2018


Ответы (2)


XOR немного переворачивает вместо того, чтобы всегда очищать его. И — это один вариант, BTR (bit-test-reset) — другой. BTR с назначением памяти очень медленный с регистровым источником, но совсем неплохо с немедленным (всего 2 мкп на Haswell, 3 на Skylake. Правда, до 4 на AMD, где стоит 2 мкп даже для btr $9, %eax. )

popf довольно медленный (9 мкп, 1 за 20 циклов на Skylake). Или на Ryzen 35 мкп и один на 13 тактов. (http://agner.org/optimize). Таким образом, оптимизация окружающего кода не будет иметь большого значения, но интересно найти способ сохранить компактный размер кода.

Вам не нужно сохранять/восстанавливать EAX самостоятельно, просто скажите компилятору, что вы хотите стереть его с помощью : "eax" в качестве списка стирания, или использовать фиктивный операнд вывода (обратите внимание, что я использую расширенный ассемблер GNU C, а не базовый).

static inline
void clear_tf(void) {
    long dummy;       // there's no type that's always 32-bit on 32-bit, and always 64 on 64-bit.  x32 uses 32-bit pointers in long mode so uintptr_t or size_t doesn't work.
   // if porting to x86-64 System V user-space: beware that push clobbers the red-zone
    __asm__ volatile("pushf \n\t"
                     "pop   %[tmp] \n\t"
                     "btr   $9, %[tmp]\n\t"   // reset bit 9
                     "push  %[tmp] \n\t"
                     "popf"
                    : [tmp] "=r"(dummy)
                    : // no inputs
                    : // no clobbers.  // "memory" // would block reordering with loads/stores.
                );
}

Или просто не трогайте никакие регистры: это тоже очень эффективно, особенно на AMD Ryzen, где нет uop-синхронизации стека и памяти-назначения И это одиночный uop.

static inline
void clear_tf(void) {
   // if porting to x86-64 System V user-space: beware that push clobbers the red-zone
    __asm__ volatile("pushf \n\t"
                     "andl $0xFFFFFEFF, (%esp) \n\t"  // 1 byte larger than the pop/btr/push version
                     "popf"
                );
    // Basic asm syntax: no clobbers.
}

Для меньшего размера кода, вероятно, подойдет btrl $9, (%esp). По-прежнему всего 2 мопов на Haswell (3 на Skylake), но на 2 байта меньше, чем andl. andb $0xfe, 1(%esp) также имеет тот же размер, но вызывает остановку переадресации хранилища и составляет 2 uop + uop-синхронизация стека на Intel при использовании после push. pop %%eax; and $0xfe, %ah; push %eax тоже такого же размера, а также 3 моп (плюс слияющий моп с частичным регистром, который выдает в цикле сам по себе на Haswell/SKL). Но на АМД красиво.


Переносимость

Кстати, в коде пользовательского пространства x86-64 System V вы не можете безопасно вставлять/выталкивать, не затирая красную зону компилятора, поэтому вы, вероятно, захотите add $-128, %rsp до push и восстановить его после.

В коде ядра нет красной зоны, поэтому push/pop внутри встроенного asm в порядке.

Windows использует другой ABI без красной зоны.

person Peter Cordes    schedule 20.07.2018
comment
@MichaelPetch: x86-64 System V ABI указывает красную зону. Я не знал, что многие операционные системы, отличные от Linux, которые используют его, не поддерживают красную зону, спасибо, что указали на это. Я хотел поместить что-то в комментарий, встроенный в код, но не было места для полной информации. Если все, что нужно, чтобы остерегаться этого, — это подтвердить, что ваша ОС его не использует, и ваш код никогда не будет перенесен в пользовательское пространство Linux, то это нормально. - person Peter Cordes; 25.07.2018

с приведенным ниже кодом он работал нормально. Спасибо

  __asm__ volatile("pushl %eax;\
                    pushfl;\
                    popl %eax;\
                    andl $0xFFFFFEFF, %eax;\
                    pushl %eax;\
                    popfl;\
                    popl %eax;"
                    );
person richejose    schedule 20.07.2018
comment
Если вы объявляете стирание в EAX, вам не нужно сохранять/восстанавливать его вокруг вашего оператора asm. asm("blah blah using %%eax extended-asm" ::: "%eax"); Или лучше используйте фиктивный выходной операнд, чтобы позволить компилятору выбрать регистр для вас. Или не трогайте eax и используйте andl $0xFFFFFEFF, (%%esp). Или для меньшего размера кода, но с остановкой переадресации хранилища, andb $0xFE, 1(%esp). Или btrl $9, (%esp) — это полезный компромисс между размером кода и числом операций, хотя popf довольно медленный (поэтому он доминирует в стоимости), и вы, вероятно, не делаете это часто. - person Peter Cordes; 20.07.2018