View Single Post
Old 30-03-2008, 01:56   #295
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3691
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();
}
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto.
E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test.
gugoXX è offline   Rispondi citando il messaggio o parte di esso