Ed ecco la parte C#. Non ho messo la lettura del counter della CPU perche' ho letto che sulle WMI dovrebbe essere proprio la frequenza istantanea, quindi va meglio la versione di ieri.
Codice:
[DllImport("CPUID_DLL.dll")]
static extern REGS GetCPUID(uint eax);
// Classe di ritorno dal C++
struct REGS
{
public int reg_eax;
public int reg_ebx;
public int reg_ecx;
public int reg_edx;
}
// Classe per contenere le stringhe associate ad un registro
// E il metodo per restituire le interessate
public class REGSSplitted
{
private string[] assoc;
public REGSSplitted(string[] stampas)
{
assoc = stampas;
}
// E' la funzione chiave, stampa le stringhe relative alle feature
// Il ritorno potrebbe anche essere string[], forse piu' chiaro
// Ho messo l'enumerable, perche' meno si ritorna agli scalari
// Meglio e' per i parallelismi futuri del PLINQ
// Una funzione che ritorna un enumerable viene valutata
// Effettivamente quanto serve (Lazy Evaluation)
// In cascata, tutto insieme, e parallelizzato nel futuro PLINQ
// Su core/processori separati.
public IEnumerable<string> GetFromInt(int src)
{
// Spettacolo. Spero sia comprensibile
// Restutisco le stringhe che hanno il bit corrispondente ad 1
var strs =
from t in Enumerable.Range(0,32)
where ( ( src & (1<<t)) !=0 )
select assoc[t];
return strs;
}
}
private static REGSSplitted ecxfeat1 = new REGSSplitted(
new []{
"Streaming SIMD Extensions 3",
"",
...
"",
"RAZ",
}
);
private static REGSSplitted edxfeat1 = new REGSSplitted(
new []{
"Floating-point unit on-Chip",
"Virtual Mode Extension",
...
"IA64 Capabilities",
"Pending Break Enable"
}
);
// Restitusice la rappresentazione dei caratteri
// relativi ai byte di un intero
static string GetStringRepr(int val)
{
// Prendo l'intero, lo converto in byte
byte[] bytearr = BitConverter.GetBytes(val);
// converto tutti i byte in caratteri
char[] chararr = bytearr.Cast<char>().ToArray();
// stringo
string ret = new string(chararr);
return ret;
}
//Restituisce i primi 4 nibble di un intero.
static byte[] FromIntToNibbleOnly4(int intero)
{
//Copiato da te.
//Lasciato funzionale perche' elegante, anche se incasinato
//L'ho scritto prima procedurale e faceva altrettanto schifo.
//Lo faccio solo per 4 valori... gli altri si cestinano comunque :)
var ogni4 = new[] { 0, 4, 8, 12 };
var nibbles = ogni4.Select(t => (byte)((intero >> t) & 15));
return nibbles.ToArray();
}
//Stampo le 4 stringhe dei 4 registri in ordine.
//Funzionale mi sembra un po' esagerato.
static void GetStringRepr(StringWriter sw,REGS complete)
{
sw.Write(GetStringRepr(complete.reg_eax));
sw.Write(GetStringRepr(complete.reg_ebx));
sw.Write(GetStringRepr(complete.reg_ecx));
sw.Write(GetStringRepr(complete.reg_edx));
}
static void Main(string[] args)
{
REGS zero = GetCPUID(0);
Console.WriteLine("CPU Vendor: {0}{1}{2}", GetStringRepr(zero.reg_ebx),
GetStringRepr(zero.reg_edx), GetStringRepr(zero.reg_ecx));
//Prendo le stringhe dei registri, e le unisco di volta in volta
StringWriter sw = new StringWriter();
REGS due = GetCPUID(0x80000002);
GetStringRepr(sw,due);
REGS tre = GetCPUID(0x80000003);
GetStringRepr(sw, tre);
REGS quattro = GetCPUID(0x80000004);
GetStringRepr(sw,quattro);
Console.WriteLine("CPU Brand : {0}", sw.ToString());
REGS uno = GetCPUID(1);
byte[] vers = FromIntToNibbleOnly4(uno.reg_eax);
// Qui non sono soddisfatto. Non so se riesco a far passare
// come parametri diversi da stampare, quelli che e' il contenuto
// dell'array.
Console.WriteLine(@"CPU Stepping: {0}, Model: {1}, Family: {2},
Processor Type: {3}", vers[0], vers[1], vers[2], vers[3]);
Console.WriteLine("");
Console.WriteLine("Features");
var stringhe = edxfeat1.GetFromInt(uno.reg_edx);
stringhe=stringhe.Union(ecxfeat1.GetFromInt(uno.reg_ecx));
//Stampo in versione funzionale. Eccessivo, ma solo per studio.
stringhe.ToList().ForEach(t => Console.WriteLine(t));
//Quella sopra e' la versione funzionale del codice seguente
//foreach (string s in stringhe)
//{
// Console.WriteLine(s);
//}
Console.ReadKey();
}