Hi Mijikai,
don't know if it will answer you
Based on An initFunction - -> Init_Processor - (When you create an userlib) :
As PB, i use include file with FASM
X64 version
Code: Select all
;
; X64 UNICODE
;
;********************************************************
; Init_Processor()
;
; Description :
; -------------
; Memorise dans un qword l'ensemble des technologies disponibles
;********************************************************
format MS64 COFF
public PB_Init_Processor
;--------------------------------------------------------
; include files
;--------------------------------------------------------
include '..\Processor_CPUID_Constants.inc'
;--------------------------------------------------------
; macro
;--------------------------------------------------------
; macro d'alignement des variables globales
Macro ASMG_bssalign value { rb (value-1) - ($-_ASMG_BSSSection + value-1) mod value }
;--------------------------------------------------------
; section code
;--------------------------------------------------------
;__________________________________________________________________________
; les registres volatiles PB sont :
; RAX, RCX, RDX, R8, R9, XMM0, XMM1, XMM2 et XMM3
; les registres volatiles MS sont :
; RAX : Return value register
; RCX, RDX, R8, R9 : First to fourth integer argument
; R10, R11 : used in syscall/sysret instructions
; XMM0 à XMM5 : First to sixth FP argument when __vectorcall is used
; YMM0 à YMM5 : First to sixth FP argument when __vectorcall is used
; YMM6:YMM15 : partie supérieure des registres
; ZMM0-ZMM15 : partie supérieure des registres
; On Intel 64 processors, CPUID clears the high 32 bits of the RAX/RBX/RCX/RDX registers in all modes
; On AMD, in 64-bit mode, this instruction (CPUID) works the same as in legacy mode except that it zeroextends 32-bit register results to 64 bits.
;__________________________________________________________________________
section '.text' code readable executable
PB_Init_Processor:
; ----------------------- CPUID availability Detection
; Détermine si l'instruction CPUID est disponible pour le processeur
; ceci avant toute opération avec CPUID
; Determines if the CPUID instruction is available to the processor
; before any operation with CPUID
; code based from AMD (40332.pdf), AMD64 Architecture Programmer's Manual, Volumes 1-5 page 165/166
PUSHFQ ; store RFLAGS on stack
POP rax ; store EFLAGS in EAX
MOV ecx, eax ; save in ECX for later testing
XOR eax, 0x0200000 ; toggle bit 21
PUSH rax ; push to stack
POPFQ ; save changed EAX to RFLAGS
PUSHFQ ; push RFLAGS to TOS
POP rax ; store EFLAGS in EAX
CMP eax, ecx ; see if bit 21 has changed
JZ no_CPUID ; if no change, no CPUID
; sauvegarde du résultat (True) dans la variable globale processor_Technologie_Avalaible
OR byte [processor_Technologie_Avalaible], processor__CPUID_Avalaible
Get_CPUID_infos:
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■ CPUID level 0 ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; INTEL
;--------
; The ID flag (bit 21) in the EFLAGS register indicates support for the CPUID instruction. If a software procedure can
; set and clear this flag, the processor executing the procedure supports the CPUID instruction. This instruction operates
; the same in non-64-bit modes and 64-bit mode.
;--------
; AMD
; Some processor implementations may Not support the CPUID instruction. Support For the CPUID
; instruction is determined by testing the RFLAGS.ID bit. If software can write this bit, then the CPUID
; instruction is supported by the processor implementation. Otherwise, execution of CPUID results in an
; invalid-opcode exception.
;--------
; retrouve le nombre d'entrées maximales pour les informations de base du CPUID
; ici CPUID est disponible
MOV eax, 0 ; standard Function
; sauvegarde du registre volatile
PUSH rbx
CPUID
; highest value the CPUID recognizes for returning basic processor information.
; The value is returned in the EAX register and is processor specific.
; valeur la plus élevée que le CPUID reconnaît pour renvoyer les informations de base du processeur.
; La valeur est renvoyée dans le registre EAX et est spécifique au processeur.
MOV qword [processor__CPUID_Level_0000_0000____Maximum_Input_Value_for_Basic_Function_CPUID_Information], rax
; A vendor identification string is also returned in EBX, EDX, and ECX.
; Une chaîne d'identification du fournisseur est également renvoyée dans EBX, EDX et ECX.
; écriture des 3 registres en mémoire à processor__Vendor_String
MOV dword [processor__Vendor_String], ebx
MOV dword [processor__Vendor_String+4], edx
MOV dword [processor__Vendor_String+8], ecx
; restauration du registre volatile
POP rbx
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■ CPUID level 1 ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; Maximum Input Value, check result, CPUID Maximum Value Limit must be >= 1 to get CPUID level 1
CMP qword [processor__CPUID_Level_0000_0000____Maximum_Input_Value_for_Basic_Function_CPUID_Information], 1
JNAE CPUID_level_bad_result
; Get CPUID level 1h infos
MOV eax, 1 ; CPUID level 1
; sauvegarde du registre volatile rbx
PUSH rbx
CPUID
; processor CPUID Level 1 result EAX
MOV dword [processor__CPUID_Level_0000_0001____ECX_optional_value_none___EAX_return_value], eax
; processor CPUID Level 1 result EBX
MOV dword [processor__CPUID_Level_0000_0001____ECX_optional_value_none___EBX_return_value], ebx
; processor CPUID Level 1 result ECX
MOV dword [processor__CPUID_Level_0000_0001____ECX_optional_value_none___ECX_return_value], ecx
; processor CPUID Level 1 result EDX
MOV dword [processor__CPUID_Level_0000_0001____ECX_optional_value_none___EDX_return_value], edx
; restauration réelle du registre volatile rbx
POP rbx
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■ CPUID level 7h ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; Maximum Input Value, check result, eax must be > = to 1 to get CPUID level 1
CMP qword [processor__CPUID_Level_0000_0000____Maximum_Input_Value_for_Basic_Function_CPUID_Information], 7
JNAE CPUID_level_bad_result
; Get CPUID level 7h infos
MOV eax, 7
MOV ecx, 0 ; sub-leaf
; sauvegarde du registre volatile rbx
PUSH rbx
CPUID
; processor__CPUID_Level_7_EAX.i
; eax Bits 31 - 00: Reports the maximum input value for supported leaf 7 sub-leaves
MOV dword [processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EAX_return_value], eax
; processor__CPUID_Level_7_EBX.i
MOV dword [processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EBX_return_value], ebx
; processor__CPUID_Level_7_ECX.i
MOV dword [processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___ECX_return_value], ecx
; processor__CPUID_Level_7_EDX.i
MOV dword [processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EDX_return_value], edx
; restauration réelle du registre volatile rbx
POP rbx
include '\Level_0x80000000\Level_0x80000000__x64.asm'
include '\Level_0x80000000\Level_0x80000001__x64.asm'
include '\Level_0x80000000\Level_0x80000002__x64.asm'
include '\Level_0x80000000\Level_0x80000003__x64.asm'
include '\Level_0x80000000\Level_0x80000004__x64.asm'
include '\Level_0x80000000\Level_0x80000006__x64.asm'
include '\Level_0x80000000\Level_0x80000007__x64.asm'
include '\Level_0x80000000\Level_0x80000008__x64.asm'
include '\Level_0x80000000\Level_0x80000009__x64.asm'
include '\Level_0x80000000\Level_0x8000000A__x64.asm'
include '\Level_0x80000000\Level_0x8000000B__x64.asm'
include '\Level_0x80000000\Level_0x8000000C__x64.asm'
include '\Level_0x80000000\Level_0x8000000D__x64.asm'
include '\Level_0x80000000\Level_0x8000000E__x64.asm'
include '\Level_0x80000000\Level_0x8000000F__x64.asm'
include '\Level_0x80000000\Level_0x80000010__x64.asm'
include '\Level_0x80000000\Level_0x80000011__x64.asm'
include '\Level_0x80000000\Level_0x80000012__x64.asm'
include '\Level_0x80000000\Level_0x80000013__x64.asm'
include '\Level_0x80000000\Level_0x80000014__x64.asm'
include '\Level_0x80000000\Level_0x80000015__x64.asm'
include '\Level_0x80000000\Level_0x80000016__x64.asm'
include '\Level_0x80000000\Level_0x80000017__x64.asm'
include '\Level_0x80000000\Level_0x80000018__x64.asm'
include '\Level_0x80000000\Level_0x80000019__x64.asm'
include '\Level_0x80000000\Level_0x8000001A__x64.asm'
include '\Level_0x80000000\Level_0x8000001B__x64.asm'
include '\Level_0x80000000\Level_0x8000001C__x64.asm'
include '\Level_0x80000000\Level_0x8000001D__x64.asm'
include '\Level_0x80000000\Level_0x8000001E__x64.asm'
include '\Level_0x80000000\Level_0x8000001F__x64.asm'
include '\Level_0x80000000\Level_0x80000020__x64.asm'
Processor_Brand_String_Not_Supported:
; ----------------------- ends with error
no_CPUID:
CPUID_level_bad_result:
EndFunction:
RET
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■ variables globales de la fonction ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
section '.data' data readable writeable
_ASMG_BSSSection:
; processor_Technologie_Avalaible.q
ASMG_bssalign 8
Public processor_Technologie_Avalaible
processor_Technologie_Avalaible:
dq 0
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■ CPUID level 0 storing values ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; cette variable recevra les valeurs respectives du registre EAX
; CPUID Maximum Value Limit
Public processor__CPUID_Level_0000_0000____Maximum_Input_Value_for_Basic_Function_CPUID_Information
processor__CPUID_Level_0000_0000____Maximum_Input_Value_for_Basic_Function_CPUID_Information:
dq 0
; Début de la chaîne d'identification du fournisseur renvoyée dans EBX, EDX et ECX, stocké en en Unicode.
; 24 caractères (ascci ->> unicode + un zéro de fin de chaine unicode)
Public processor__Vendor_String
processor__Vendor_String:
db 12 dup 0
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■ CPUID level 1 storing values ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; ces variables recevront les valeurs respectives des registres EAX, EBX, ECX et EDX
; après l'apel de CPUID avec EAX = 1
Public processor__CPUID_Level_0000_0001____ECX_optional_value_none___EAX_return_value
processor__CPUID_Level_0000_0001____ECX_optional_value_none___EAX_return_value:
dq 0
Public processor__CPUID_Level_0000_0001____ECX_optional_value_none___EBX_return_value
processor__CPUID_Level_0000_0001____ECX_optional_value_none___EBX_return_value:
dq 0
Public processor__CPUID_Level_0000_0001____ECX_optional_value_none___ECX_return_value
processor__CPUID_Level_0000_0001____ECX_optional_value_none___ECX_return_value:
dq 0
Public processor__CPUID_Level_0000_0001____ECX_optional_value_none___EDX_return_value
processor__CPUID_Level_0000_0001____ECX_optional_value_none___EDX_return_value:
dq 0
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■ CPUID level 7h storing values ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; ces variables recevront les valeurs respectives des registres EAX, EBX, ECX et EDX
; après l'apel de CPUID avec EAX = 7h
Public processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EAX_return_value
processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EAX_return_value:
dq 0
Public processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EBX_return_value
processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EBX_return_value:
dq 0
Public processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___ECX_return_value
processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___ECX_return_value:
dq 0
Public processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EDX_return_value
processor__CPUID_Level_0000_0007____ECX_optional_value_0000_0000___EDX_return_value:
dq 0
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000000__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000001__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000002__x64.asm'
;include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000003__x64.asm'
;include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000004__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000006__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000007__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000008__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000009__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000A__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000B__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000C__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000D__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000E__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000000F__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000010__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000011__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000012__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000013__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000014__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000015__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000016__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000017__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000018__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000019__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001A__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001B__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001C__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001D__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001E__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x8000001F__x64.asm'
include '\Level_0x80000000\Var_globales__CPUID_Level_0x80000020__x64.asm'
and for example the Brand string asm file
Code: Select all
;
; X64 UNICODE
;
;********************************************************
; Processor__Brand_String.i
; (
; bufferBrand.i
; )
;
; Description :
; -------------
; Recopie la chaine définissant la marque du processeur du processeur dans le buffer passé en paramètre
;********************************************************
format MS64 COFF
public PB_Processor__Brand_String
;--------------------------------------------------------
; include files
;--------------------------------------------------------
include '..\Processor_CPUID_Constants.inc'
include '..\..\Constantes_PureBasic_x64.inc'
;--------------------------------------------------------
; paramètre de la fonction
;--------------------------------------------------------
; bufferBrand.i
bufferBrand equ rsp+8
;--------------------------------------------------------
; variables globales librairie : données CPUID
;--------------------------------------------------------
extrn processor__CPUID_Level_8000_0000____Maximum_Input_Value_for_Extended_Function_CPUID_Information
extrn processor__Brand_String
;--------------------------------------------------------
; section code
;--------------------------------------------------------
;__________________________________________________________________________
; les registres volatiles PB sont :
; RAX, RCX, RDX, R8, R9, XMM0, XMM1, XMM2 et XMM3
; les registres volatiles MS sont :
; RAX : Return value register
; RCX, RDX, R8, R9 : First to fourth integer argument
; R10, R11 : used in syscall/sysret instructions
; XMM0 à XMM5 : First to sixth FP argument when __vectorcall is used
; YMM0 à YMM5 : First to sixth FP argument when __vectorcall is used
; YMM6:YMM15 : partie supérieure des registres
; ZMM0-ZMM15 : partie supérieure des registres
;__________________________________________________________________________
section '.text' code readable executable
PB_Processor__Brand_String:
; sauvegarde du paramètre sur la pile
; MOV qword [bufferBrand], rcx
; Check pointer bufferBrand (0 = error)
TEST rcx, rcx
JZ Error__bufferBrand_Null
; check result level 0x80000000/0x80000004
MOV r8d, dword [processor__CPUID_Level_8000_0000____Maximum_Input_Value_for_Extended_Function_CPUID_Information]
TEST r8d, 0x80000000
JZ Error__bufferBrand_Null
CMP r8d, 0x80000004
JNAE Error__bufferBrand_Null
; rdx point original first Ascii string level 0x80000002 (processor__Brand_String)
MOV rdx , processor__Brand_String
; r8 point destination buffer (bufferBrand)
MOV r8, rcx
; loop counter, 48 Ascii char to recopy
MOV rcx, 48
; Ascii char to Unicode char, so upper part of ax to 0
MOV ax, 0
; loop start
.write_Brand_String:
; al = Ascii char
MOV al, [rdx]
; write Unicode char to destination buffer
MOV [r8], ax
; increment pointers
INC rdx
ADD r8, 2
; first decrement ecx and after test it to 0, jmp if no 0 to .write_Brand_String
LOOP .write_Brand_String
; write 0 of end string (adresse buffer base + 96)
MOV word [r8], 0
Ok:
; it's Ok, return #True
MOV rax, True
EndFunction:
RET
;------------------ Errors ------------------
Error__bufferBrand_Null:
; error, return #False
XOR rax, rax
JMP EndFunction
and a tipical PB call of this function, the buffer receives unicode format of the string
on my computer : Intel(R) Core(TM) i5-7400 CPU @ 3.00GHz
(CPUID level 80000002h, CPUID level 80000003h & CPUID level 80000004h)
code for 80000002h, it's close for 80000003h & level 80000004h
Code: Select all
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
;■ CPUID level 80000002h ■
;■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
; Get CPUID level 80000002h infos
MOV eax, 80000002h
; sauvegarde du registre volatile rbx
PUSH rbx
CPUID
; ; processor CPUID Level 80000002h result EAX
MOV dword [processor__Brand_String], eax
; ; processor CPUID Level 80000002h result EBX
MOV dword [processor__Brand_String+4], ebx
; ; processor CPUID Level 80000002h result ECX
MOV dword [processor__Brand_String+8], ecx
; ; processor CPUID Level 80000002h result EDX
MOV dword [processor__Brand_String+12], edx
; restauration du registre volatile rbx
POP rbx
Code: Select all
*bufferBrand = AllocateMemory(98)
If *bufferBrand = #Null
MessageRequester(Error, BadAllocateMemory, #PB_MessageRequester_Error)
End
EndIf
If Processor__Brand_String(*bufferBrand) = #False
MessageRequester(Error, BadAllocateMemory, #PB_MessageRequester_Error)
FreeMemory(*bufferBrand)
End
EndIf
Debug PeekS(*bufferBrand)