Get CPU Informations (Name, Speed, Cores)

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
Schnapsidee
Posts: 10
Joined: Jul 07, 2017 20:20

Get CPU Informations (Name, Speed, Cores)

Post by Schnapsidee »

Hello :)

I wrote this little program, which displays your CPU name, the speed and the number of cores. Let me know, if it works. :)

It's using a special CPUID-Function to get the CPU name. However, older CPUs (Pentium II and older) don't support this function and the program has to guess, which CPU is installed.
Sample output:
CPU: Intel(R) Core(TM) i5-6500 CPU @ 3.20GHz
4x 3200 MHz

Code: Select all

Function GetCPUSpeed As Integer
   Dim As UlongInt t_start, t_ende
   Asm  rdtsc
   Asm  mov dword ptr [t_start + 4], edx
   Asm  mov dword ptr [t_start], eax
   Sleep 1000
   Asm  rdtsc
   Asm  mov dword ptr [t_ende + 4], edx
   Asm  mov dword ptr [t_ende], eax
   t_ende -= t_start
   t_ende \= 1000000
   If (t_ende Mod 100) > 70 Then
      Return ((t_ende\100)+1)*100
   Else
      Return t_ende
   End If
End Function

Function GetCPUCores As UByte
   Dim As UByte numcores

   Asm
      mov eax,&h0A
      cpuid
      mov [numcores],al
   End Asm
   If numcores = 0 Then numcores = 1
   Return numcores
End Function

Function GetCPUName As String
   Dim As String nam
   Dim As UByte nam1,nam2,nam3,nam4
   Dim As ULong tmp
   
   Asm
      mov eax,0x80000000
      cpuid
      mov [tmp],eax
   End Asm
   
   If tmp>=&h80000000 Then            'Brand String Supported
   
      Dim As ZString*49 nam_brand
      Asm
         mov eax, &h80000002
         cpuid
         mov [nam_brand], eax
         mov [nam_brand+4], ebx
         mov [nam_brand+8], ecx
         mov [nam_brand+12], edx
         mov eax, &h80000003
         cpuid
         mov [nam_brand+16], eax
         mov [nam_brand+20], ebx
         mov [nam_brand+24], ecx
         mov [nam_brand+28], edx
         mov eax, &h80000004
         cpuid
         mov [nam_brand+32], eax
         mov [nam_brand+36], ebx
         mov [nam_brand+40], ecx
         mov [nam_brand+44], edx
        End Asm
       
        nam=nam_brand

   Else                        'Brand String Not Supported

      Dim As Zstring * 13 vendorID
      Dim As ULong family,model,emodel,cpuid2

      Asm
         xor eax, eax
         cpuid
         mov [vendorID], ebx
         mov [vendorID+4], edx
         mov [vendorID+8], ecx
         mov eax,1
         cpuid
         mov [cpuid2],eax
      End Asm
     
      model = cpuid2 shl (31 - 7)
      model = model shr (31 - 7 + 4)
     
      emodel = cpuid2 shl (31 - 19)
      emodel = emodel shr (31 - 19 + 16)
     
      family = cpuid2 shl (31 - 11)
      family = family shr (31 - 11 + 8)
     
      Var modelstr="&h"+Str(emodel)+Hex(model)
      model=ValUInt(modelstr)
     
      Select Case vendorID
         Case "GenuineIntel"
            nam="Intel(R) "
            Select Case family
               
               Case 3
                  nam+="x386"
               Case 4
                  nam+="x486"
               Case 5
                  nam+="Pentium I"
               Case 6
                  Select Case model
                     Case 1
                        nam+="Pentium Pro"
                     Case 3 To 6
                        nam+="Pentium II"
                     Case 6
                        nam+="Celeron"
                     Case 7,8,10,11
                        nam+="Pentium III"
                     Case 9,13
                        nam+="Pentium M"
                     Case Else
                        nam+="P6"
                  End Select
               Case 15
                  nam+="Pentium 4"
            End Select
         Case "AuthenticAMD"
            nam="AMD "
            Select Case family
               Case 4
                  nam+="x486"
               Case 6
                  nam+="Athlon"
               Case 15
                  nam+="Athlon 64"
            End Select
         Case Else
            nam=vendorID+" "
      End Select
     
   End If

   Return nam
End Function

Print "CPU:    "+GetCPUName
Print "        "+Str(GetCPUCores)+"x "+Str(GetCPUSpeed)+" MHz"
The "GetCPUSpeed"-Function wasn't written by me. I found it a while ago on the forums and changed it up a little.
Last edited by Schnapsidee on Jul 08, 2017 16:46, edited 1 time in total.
St_W
Posts: 1619
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: Get CPU Informations (Name, Speed, Cores)

Post by St_W »

The code does not compile with the 32-bit compiler, and neither does it using the 64-bit compiler.
C:\FreeBasic\FreeBASIC-1.05.0-win32\fbc -gen gcc -s console "test.bas"
test.asm: Assembler messages:
test.asm:24: Error: operand type mismatch for `mov'
test.asm:27: Error: operand size mismatch for `mov'
test.asm:38: Error: operand type mismatch for `mov'
test.asm:41: Error: operand size mismatch for `mov'
To fix it the ULongInt pointers need to be declared as "dword ptr"s. And instead of UInteger ULong should be used. Here's a fixed version that should compile:

Code: Select all

Function GetCPUSpeed As Integer
   Dim As UlongInt t_start, t_ende
   Asm  rdtsc
   Asm  mov dword ptr [t_start + 4], edx
   Asm  mov dword ptr [t_start], eax
   Sleep 1000
   Asm  rdtsc
   Asm  mov dword ptr [t_ende + 4], edx
   Asm  mov dword ptr [t_ende], eax
   t_ende -= t_start
   t_ende \= 1000000
   If (t_ende Mod 100) > 70 Then
      Return ((t_ende\100)+1)*100
   Else
      Return t_ende
   End If
End Function

Function GetCPUCores As UByte
   Dim As UByte numcores

   Asm
      mov eax,&h0A
      cpuid
      mov [numcores],al
   End Asm
   If numcores = 0 Then numcores = 1
   Return numcores
End Function

Function GetCPUName As String
   Dim As String nam
   Dim As UByte nam1,nam2,nam3,nam4
   Dim As ULong tmp
   
   Asm
      mov eax,0x80000000
      cpuid
      mov [tmp],eax
   End Asm
   
   If tmp>=&h80000000 Then            'Brand String Supported
   
      Dim As ZString*49 nam_brand
      Asm
         mov eax, &h80000002
         cpuid
         mov [nam_brand], eax
         mov [nam_brand+4], ebx
         mov [nam_brand+8], ecx
         mov [nam_brand+12], edx
         mov eax, &h80000003
         cpuid
         mov [nam_brand+16], eax
         mov [nam_brand+20], ebx
         mov [nam_brand+24], ecx
         mov [nam_brand+28], edx
         mov eax, &h80000004
         cpuid
         mov [nam_brand+32], eax
         mov [nam_brand+36], ebx
         mov [nam_brand+40], ecx
         mov [nam_brand+44], edx
        End Asm
       
        nam=nam_brand

   Else                        'Brand String Not Supported

      Dim As Zstring * 13 vendorID
      Dim As ULong family,model,emodel,cpuid2

      Asm
         xor eax, eax
         cpuid
         mov [vendorID], ebx
         mov [vendorID+4], edx
         mov [vendorID+8], ecx
         mov eax,1
         cpuid
         mov [cpuid2],eax
      End Asm
      
      model = cpuid2 shl (31 - 7)
      model = model shr (31 - 7 + 4)
      
      emodel = cpuid2 shl (31 - 19)
      emodel = emodel shr (31 - 19 + 16)
      
      family = cpuid2 shl (31 - 11)
      family = family shr (31 - 11 + 8)
      
      Var modelstr="&h"+Str(emodel)+Hex(model)
      model=ValUInt(modelstr)
      
      Select Case vendorID
         Case "GenuineIntel"
            nam="Intel(R) "
            Select Case family
               
               Case 3
                  nam+="x386"
               Case 4
                  nam+="x486"
               Case 5
                  nam+="Pentium I"
               Case 6
                  Select Case model
                     Case 1
                        nam+="Pentium Pro"
                     Case 3 To 6
                        nam+="Pentium II"
                     Case 6
                        nam+="Celeron"
                     Case 7,8,10,11
                        nam+="Pentium III"
                     Case 9,13
                        nam+="Pentium M"
                     Case Else
                        nam+="P6"
                  End Select
               Case 15
                  nam+="Pentium 4"
            End Select
         Case "AuthenticAMD"
            nam="AMD "
            Select Case family
               Case 4
                  nam+="x486"
               Case 6
                  nam+="Athlon"
               Case 15
                  nam+="Athlon 64"
            End Select
         Case Else
            nam=vendorID+" "
      End Select
      
   End If

   Return nam
End Function

Print "CPU:    "+GetCPUName
Print "        "+Str(GetCPUCores)+"x "+Str(GetCPUSpeed)+" MHz"
UEZ
Posts: 972
Joined: May 05, 2017 19:59
Location: Germany

Re: Get CPU Informations (Name, Speed, Cores)

Post by UEZ »

I get a wrong output for my CPU:

Code: Select all

CPU:    Intel(R) Core(TM) i5-4300U CPU @ 1.90GHz
        3x 2600 MHz

Should be something like this here:

Code: Select all

Processors
-------------------------------------------------------------------------

Number of sockets		1
Number of threads		4

APICs
-------------------------------------------------------------------------

Socket 0	
	-- Core 0	
		-- Thread 0	0
		-- Thread 1	1
	-- Core 1	
		-- Thread 0	2
		-- Thread 1	3

Timers
-------------------------------------------------------------------------

	ACPI timer		3.580 MHz
	Perf timer		2.436 MHz
	Sys timer		1.000 KHz


Processors Information
-------------------------------------------------------------------------

Socket 1			ID = 0
	Number of cores		2 (max 2)
	Number of threads	4 (max 4)
	Name			Intel Core i5 4300U
	Codename		Haswell ULT
	Specification		Intel(R) Core(TM) i5-4300U CPU @ 1.90GHz
	Package (platform ID)	Socket 1168 BGA (0x6)
	CPUID			6.5.1
	Extended CPUID		6.45
	Core Stepping		C0
	Technology		22 nm
	TDP Limit		15.0 Watts
	Tjmax			100.0 °C
	Core Speed		798.4 MHz
	Multiplier x Bus Speed	8.0 x 99.8 MHz
	Stock frequency		1900 MHz
	Instructions sets	MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, EM64T, VT-x, AES, AVX, AVX2, FMA3
	L1 Data cache		2 x 32 KBytes, 8-way set associative, 64-byte line size
	L1 Instruction cache	2 x 32 KBytes, 8-way set associative, 64-byte line size
	L2 cache		2 x 256 KBytes, 8-way set associative, 64-byte line size
	L3 cache		3 MBytes, 12-way set associative, 64-byte line size
Schnapsidee
Posts: 10
Joined: Jul 07, 2017 20:20

Re: Get CPU Informations (Name, Speed, Cores)

Post by Schnapsidee »

@St_W:
Hmm, it is working for me on 32bit Linux and DOS (FBC 1.05.0).
alfakilo
Posts: 117
Joined: Oct 02, 2009 9:18
Location: Estonia

Re: Get CPU Informations (Name, Speed, Cores)

Post by alfakilo »

Hi ,i got...
Output :
CPU: AMD A9-9419 RADEON R5, 5 COMPUTE CORES 2C+3G
1x2944 Mhz


Supposed to be 2 cores (2.90 ghz - 3.45ghz)
St_W
Posts: 1619
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: Get CPU Informations (Name, Speed, Cores)

Post by St_W »

UEZ wrote:I get a wrong output for my CPU
I didn't notice first, but I get a wrong output too:

Code: Select all

CPU:    Intel(R) Core(TM)2 Quad CPU    Q6600  @ 2.40GHz
        2x 2515 MHz
The number of cores should be 4.
The speed estimation is not bad - in reality my CPU runs at 2.47 GHz currently. However, the implemtation using the TSC may cause inaccuracies with certain system configurations.
Schnapsidee wrote:@St_W:
Hmm, it is working for me on 32bit Linux and DOS (FBC 1.05.0).
It only works with the 32-bit compiler and the gas backend. In general, try to write clean and portable code and avoid the use of (inline) assembly, which is not fully possible in this case, however.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Get CPU Informations (Name, Speed, Cores)

Post by dodicat »

This works on Win 10

Code: Select all

#include "file.bi"
Function loadfile(file As String) As String
    Var  f=Freefile
    if fileexists(file) =0 then print file + " not found":sleep:end
    Open file For Binary Access Read As #f
    Dim As String text
    If Lof(1) > 0 Then
        text = String(Lof(f), 0)
        Get #f, , text
    End If
    Close #f
    Return text
End Function

Sub stringsplit(byval s As String,chars As String,result() As String)
    redim result(0)
    Dim As String var1,var2
Dim As long pst
      #macro split(stri)
    pst=Instr(stri,chars)
    var1="":var2=""
    If pst<>0 Then
    var1=Mid(stri,1,pst-1)
    var2=Mid(stri,pst+1)
    Else
    var1=stri
End if
    if len(var1) then 
    redim preserve result(1 to ubound(result)+1)
    result(ubound(result))=var1
    end if
    #endmacro
   Do
   split(s):s=var2
Loop Until var2=""
End Sub

print "Please wait"
shell "dxdiag /t  computerinfo.txt"
redim as string g()
StringSplit(loadfile("computerinfo.txt"),"DxDiag Notes",g())
print g(1)
sleep
kill "computerinfo.txt" 
Should only show one page.
Saves asm headaches.
Schnapsidee
Posts: 10
Joined: Jul 07, 2017 20:20

Re: Get CPU Informations (Name, Speed, Cores)

Post by Schnapsidee »

St_W wrote:In general, try to write clean and portable code and avoid the use of (inline) assembly, which is not fully possible in this case, however.
The ASM is needed, because of the CPUID-function (getting the CPU-Name), which seems to work really good. But counting the cores doesn't really work for some reason. I will take a look on it. I don't know how to make it more portable without ASM though (in sense of OS independent). I have edited the first post to make it work with 32bit and 64bit FBC.
St_W
Posts: 1619
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

Re: Get CPU Informations (Name, Speed, Cores)

Post by St_W »

Schnapsidee wrote:The ASM is needed, because of the CPUID-function (getting the CPU-Name), which seems to work really good.
Of course, that's what I wanted to express with "which is not fully possible in this case, however" and "In general". Sorry if I could not describe it accurately.

The new version compiles fine for me on x86 and x86_64 on Windows 10.

The CPU speed estimation is worse (or does not work?) in the 64-bit version on my PC: I get about 3.1 GHz instead of 2.47 GHz.
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Get CPU Informations (Name, Speed, Cores)

Post by badidea »

Missing 1 core:

CPU: Intel(R) Core(TM) i7-5600U CPU @ 2.60GHz
3x 2601 MHz

Linux, 32-bit fbc
Post Reply