Вы можете и должны использовать GNU C #include <cpuid.h>
в своем собственном коде вместо встроенного ассемблера GNU C. (Как вызвать cpuid в Linux?) Пример компиляции Godbolt, включая проверку доступности CPUID в 32-битном режиме.
x86-64 гарантирует доступность CPUID; вам нужно только проверить это, если ваш код может работать на 486 или более ранней версии. Но 486 вообще не может запускать 64-битный код.
Настоящая проблема с вашим кодом заключается в том, что он не пытается перевернуть бит идентификатора. По-видимому, 0
является нормальным для его текущего состояния. https://wiki.osdev.org/CPUID#Checking_CPUID_availability показывает стандартный код обнаружения (для 32 -битовый режим Intel-синтаксис, но достаточно простой для переноса), который использует XOR для назначения памяти перед регистрацией popf / pushf / pop, чтобы увидеть, была ли принята настройка. (Затем он восстанавливает исходные EFLAGS, что, вероятно, не нужно.)
Реализацию встроенного ассемблера GNU C см. в собственном cpuid.h
GCC (github), где это делается внутри блока #ifndef __x86_64__
в __get_cpuid_max
. У него даже есть диалектные альтернативы для синтаксиса AT&T и Intel, поэтому код, использующий #include <cpuid.h>
, не ломается, если скомпилирован с -masm=intel
.
Перенос этого на x86-64 позволит вам убедиться, что он действительно работает, если вам интересно.
Кроме того, ваши push/pop небезопасны в Linux/Mac (x86-64 System V): вы наступаете на красную зону. Вам нужно add $-128, %rsp
до и sub $-128, %rsp
после, чтобы ваш push/pop не наступал на красную зону ниже RSP компилятора, где он может хранить локальные переменные. См. раздел Использование регистра базового указателя во встроенном ассемблере C++.
-128
подходит для imm8, а +128
нет, поэтому я предлагаю add/sub $-128
вместо sub/add $128
.
person
Peter Cordes
schedule
15.03.2021