Автор: Эрик Палмер (Eric Palmer)
При разработке для платформ x64 в Visual Studio .NET* 2005 программисты уже не могут использовать встроенный ассемблерный код, как в случае 32-разрядного кода. Это вынуждает программистов либо полагаться на код C/C++, используя встроенные средства, либо использовать трудоемкое создание 64-разрядной MASM (.asm) версии функции. К сожалению, реализация встроенного средства VS .Net 2005 для CPUID (__cpuid) распознает только входные параметры в регистре eax, и не распознает определенные позже входные параметры в ecx, которые требуются для запросов, связанных с параметрами кэша и определенными многоядерными характеристиками. Таким образом, для использования функции CPUID в полном объеме требуется 64-разрядный .asm листинг.
Следующие примеры кодов демонстрируют, как использовать команды CUPID и RDSTC с VS.NET 2005 для 64-разрядных (x64) платформ. Команда CPUID обычно применяется для получения подробной информации о ЦП системы, а RDTSC используется для считывания внутреннего счетчика системного времени ЦП для целей синхронизации и измерения производительности. Встроенное средство RDTSC (__rdtsc) должно работать, как и предполагается, и может использоваться вместо встроенного ассемблера.
Для компоновки 64-разрядного файла .asm создайте пользовательский шаг компоновки, который вызывает 64-разрядный MASM, "ml64.exe", как показано на приведенном ниже моментальном снимке экрана. Для 32-разрядной конфигурации файл cpuid64.asm компоновать не следует, поэтому для платформы Win32 установите значение Да для опции Общие -> Исключить из компоновки.

(Для увеличения нажмите на изображение)
Показанный ниже файл заголовка (cpuid_32_64.h) создает единое определение функций _CPUID и _RDTSC, которое можно использовать и в 32-разрядных, и в 64-разрядных компоновках. Для 64-разрядных компоновок _CPUID использует .asm-функцию cpuid64, а _RDTSC использует встроенное средство __rdtsc. Для 32-разрядных компоновок _CPUID использует функцию встроенного ассемблера cpuid32, а _RDTSC - функцию _inl_rdtsc32.
В представленном ниже файле C (cpuid_32_64.c) показано два примера. В первом из них - GetCoresPerPackage() - вызывается _CPUID с eax=4 и ecx=0 для считывания детерминированных параметров кэша первого набора, представленных ЦП, и извлечения поля, указывающего число ядер процессора в процессорном пакете. (Например, эта функция будет возвращать значение 1 в случае одноядерного процессора Intel® Pentium® 4 и значение 2 в случае двухъядерного процессора Intel® Pentium® D.) Если в этой функции на платформе x64 использовалось бы встроенное средство __cpuid вместо функции cpuid64, входящее значение ecx было бы недетерминированным, и значение вывода было бы недостоверным. Во втором примере функция timeSomethingExample() дважды вызывает _RDTSC и вычисляет число тактов счетчика в цикле. Пример _CPUID показывает, как можно использовать одно и то же определение для вызова либо 64-разрядного кода .asm, либо 32-разрядного встроенного ассемблера, а в примере _RDTSC показано, как с помощью одного определения можно вызывать либо 64--разрядное встроенное средство, либо 32-разрядный встроенный ассемблер.
И в примере _CPUID, и в примере _RDTSC показано создание служебных функций, явно портируемых с платформ Win32 на платформы x64 в тех случаях, когда для каждой платформы требуется свой базовый код. Кроме того, функция cpuid64 позволяет обойти недостаток встроенного средства __cpuid, обеспечивая возможность и 32-разрядным, и 64-разрядным приложениям полностью использовать возможности команды CPUID.
Файл заголовка (cpuid_32_64.h):