Размер шрифта:
Как на Ассемблере получить строку названия процессора | Образ мышления: Assembler | Blog. Just Blog

Как на Ассемблере получить строку названия процессора | Образ мышления: Assembler | Blog. Just Blog

Без кейворда

При вызове инструкция CPUID по содержимому регистра EAX определяет какую информацию о процессоре необходимо вернуть. Вся информация, даже текстовая, возвращается в регистрах EAX, EBX, ECX и EDX. Поэтому, если их значения будут нужны для дальнейшей работы, то перед вызовом СPUID их надо сохранить. При EAX=0 CPUID возвращает в регистрах EBX, ECX и EDX идентификатор производителя процессора (Vendor ID) в виде 12 символов ASCII. В приведенной ниже табличке список самых распространенных идентификаторов производителей процессоров.

ASCII-строкаHEX-значения EBX:EDX:ECXПроизводительGenuineIntel756E6547:49656E69:6C65746EIntelAuthenticAMD68747541:69746E65:444D4163AMDCyrixInstead69727943:736E4978:64616574CyrixCentaurHauls746E6543:48727561:736C7561CentaurSiS SiS SiS20536953:20536953:20536953SiSNexGenDriven4778654E:72446E65:6E657669NexGenGenuineTMx86756E6547:54656E69:3638784DTransmetaRiseRiseRise65736952:65736952:65736952RiseUMC UMC UMC20434D55:20434D55:20434D55UMCGeode by NSC646F6547:79622065:43534E20National Semiconductor Но это лишь общее название производителя, а нам надо получить полное наименование. Для этого надо последовательно вызвать команду CPUID с параметрами в EAX = 80000002h, 80000003h и 80000004h. На каждый запрос в регистрах EAX:EBX:ECX:EDX будет возвращаться фрагмент 48-символьной строки полного наименования процессора, например, что-то типа Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz. Если строка короче 48 символов, то она будет дополняться пробелами, причем в разных местах. Для удобного получения строки названия процессора я написал вот такую функцию.

  1. ;-------------------------------------------------------------------
  2. ; Функция получения строки названия процессора
  3. ;-------------------------------------------------------------------
  4. ; Параметры:
  5. ; lpBuff - указатель на строку-приемник
  6. ; dFixString - надо ли чистить результат от лишних пробелов и
  7. ; заменять строки (TM) и (R) на отдельные символы
  8. ;-------------------------------------------------------------------
  9. proc GetCPUString lpBuff : DWORD , dFixString : DWORD
  10. pusha
  11. ; Указатель на строку-приемник
  12. movesi , [ lpBuff ]
  13. movedi , esi
  14. cld
  15. ; Прочитать информацию о процессоре
  16. moveax , 80000002h
  17. @ @ :
  18. pusheax
  19. cpuid
  20. stosd
  21. xchgeax , ebx
  22. stosd
  23. xchgeax , ecx
  24. stosd
  25. xchgeax , edx
  26. stosd
  27. popeax
  28. inceax
  29. cmpeax , 80000004h
  30. jbe @ b
  31. ; Привести строку к формату ASCIIZ
  32. xoreax , eax
  33. stosb
  34. ; Нужно ли чистить строку?
  35. cmp [ dFixString ] , 0
  36. je . loc_ret
  37. ; Почистить строку от лишних и неправильных символов
  38. movedi , esi
  39. @ @ :
  40. ; Убрать лидирующие пробелы, если они есть
  41. cmpbyte [ esi ] , ' '
  42. jne @ f
  43. incesi
  44. jmp @ b
  45. @ @ :
  46. xorebx , ebx
  47. . loc_clean_string :
  48. lodsb
  49. cmpal , ' '
  50. jnz @ f
  51. ; Убрать повторяющиеся пробелы
  52. cmpbl , 1
  53. je . loc_clean_string
  54. ; Установить флажок, что начались пробелы
  55. movbl , 1
  56. jmp . loc_store_char
  57. @ @ :
  58. ; Сбросить флажок пробелов
  59. movbl , 0
  60. ; Преобразовать символы "(R)" в один
  61. cmpal , '('
  62. jne @ f
  63. cmpword [ esi ] , 'R)'
  64. jne @ f
  65. ; ESI + 2
  66. lodsw
  67. ; Символ (R)
  68. moval , 0AEh
  69. jmp . loc_store_char
  70. @ @ :
  71. ; Преобразовать символы "(TM)" в один
  72. cmpdword [ esi - 1 ] , '(TM)'
  73. je @ f
  74. ; Написание может быть различным
  75. cmpdword [ esi - 1 ] , '(tm)'
  76. jne . loc_store_char
  77. @ @ :
  78. ; ESI + 3
  79. lodsw
  80. lodsb
  81. ; Символ (TM)
  82. moval , 099h
  83. . loc_store_char :
  84. ; Записать символ в строку
  85. stosb
  86. ; Конец строки достигнут?
  87. oral , al
  88. jnz . loc_clean_string
  89. ; Удалить финальный пробел если есть
  90. cmpbyte [ edi - 1 ] , ' '
  91. jne . loc_ret
  92. movbyte [ edi - 1 ] , 0
  93. . loc_ret :
  94. popa
  95. ret
  96. endp

Параметры вызова: lpBuff - указатель на строку-приемник в формате ASCIIZ, куда будет записано название процессора. Строка должна быть не менее 49 символов длиной с учетом финального нулевого символа. dFixString - заменять или нет в названии процессора текстовые строки "(TM)" и "(R)" на соответствующие символы, а также надо ли удалять из строки лишние пробелы (начальные, финальные, два и более пробелов подряд). Так, например, при вызове функции с параметром dFixString = TRUE, исходная строка Intel(R) Core(TM) i7 CPU 920 @ 2.67GHz будет заменена на красивую строчку Intel® Core™ i7 CPU 920 @ 2.67GHz.

В приложении пример программы с исходным текстом, показывающей Vendor ID и полное название вашего процессора. Файл "x86 Architecture CPUID Manual" - подробное описание всех параметров команды CPUID и расшифровкой возвращаемых ей значений (на английском).

📎📎📎📎📎📎📎📎📎📎