Get CPU Informations (Name, Speed, Cores)

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

Get CPU Informations (Name, Speed, Cores)

Postby Schnapsidee » Jul 07, 2017 20:30

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: 1508
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

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

Postby St_W » Jul 08, 2017 12:52

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: 635
Joined: May 05, 2017 19:59
Location: Germany

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

Postby UEZ » Jul 08, 2017 14:11

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)

Postby Schnapsidee » Jul 08, 2017 14:12

@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)

Postby alfakilo » Jul 08, 2017 15:32

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: 1508
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

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

Postby St_W » Jul 08, 2017 15:42

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: 6726
Joined: Jan 10, 2006 20:30
Location: Scotland

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

Postby dodicat » Jul 08, 2017 15:56

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)

Postby Schnapsidee » Jul 08, 2017 16:46

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: 1508
Joined: Feb 11, 2009 14:24
Location: Austria
Contact:

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

Postby St_W » Jul 08, 2017 17:34

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: 2152
Joined: May 24, 2007 22:10
Location: The Netherlands

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

Postby badidea » Jul 09, 2017 14:35

Missing 1 core:

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

Linux, 32-bit fbc

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 3 guests