PDA

Visualizza versione completa : [C/C++] Bios ID e CPU ID


pholcus
06-12-2004, 23.48.48
Ciao..

Qualcuno avrebbe del codice c o c++ per ottenere il numero di serie della cpu o un qualche ID?

Mi servirebbe anche l'id della motherboard o del bios..

Ciao!!

LoryOne
07-12-2004, 10.51.18
Per quanto riguarda il CPU ID qui ho trovato qualcosa ma è in Delphi
http://www.devarchive.com/f172.html
Non dovrebbe essere difficile effettuare il porting in C++ ;)

pholcus
07-12-2004, 11.03.44
L'avevo trovato anch'io :)

Beh di delphi io nn so assolutamente nulla :)..

vedo se riesco a combinare qualcosa col c++ builder..

Cercando su google ho letto che in ogni motherboard viene segnata la data di fabbricazione ( ora compresa ) ..

Se riuscissi a trovare il modo di recuperla sarebbe perfetto..

Webmasteeeeeeeeeerrrr?!? :p

LoryOne
07-12-2004, 11.32.31
Beh di delphi io nn so assolutamente nulla ..


Manco io ne so molto ma in quel codice li c'è veramente poco Delphi da conoscere.
Il fulcro del codice sta nelle funzioni in assembly.
Compilano entrambe un array.
Comunque, per quel poco che mi ricordo di Pascal, '$' viene utilizzato per i valori esadecimali.
shr ed shl sono shift right e shift left, ossia '<<' e '>>'

pholcus
07-12-2004, 22.03.39
Help!
Mi aiutate a mettere il codice assembly in un programma scritto in c++? :)

PS: ho trovato dei componenti per l'ID della motherboard sempre fatti dallo stesso autore del programmino sopra, ma nn mi si installano in c++ builder..

Quello che mi servirebbe di piu' e' riuscire a trovare la data di produzione del bios o della motherboard..

Ciao e grazie ancora

LoryOne
08-12-2004, 11.31.54
Beh, prima di tutto è necessario sapere se per inserire codice inline utilizzi la sintassi Intel oppure AT&T http://www.codeproject.com/cpp/gccasm.asp e non è cosa da poco.

pholcus
08-12-2004, 13.41.19
Ho fatto copia e incolla dell'assembly nel file che mi hai postato..

Per compilare compila correttamente, ma ho sicuramente sbagliato a portare la funzione in c++..

function GetCPUID : TCPUID; assembler; register;
asm
PUSH EBX {Save affected register}
PUSH EDI
MOV EDI,EAX {@Resukt}
MOV EAX,1
DW $A20F {CPUID Command}
STOSD {CPUID[1]}
MOV EAX,EBX
STOSD {CPUID[2]}
MOV EAX,ECX
STOSD {CPUID[3]}
MOV EAX,EDX
STOSD {CPUID[4]}
POP EDI {Restore registers}
POP EBX
end;

in c/c++ come dovrebbe essere?


long int GetCPUID(){
asm {
PUSH EBX //;{Save affected register}
PUSH EDI
MOV EDI,EAX //;{@Resukt}
MOV EAX,1
DW 0xA20F //;{CPUID Command}
STOSD //; {CPUID[1]}
MOV EAX,EBX
STOSD //;{CPUID[2]}
MOV EAX,ECX
STOSD //;{CPUID[3]}
MOV EAX,EDX
STOSD //;{CPUID[4]}
POP EDI //; {Restore registers}
POP EBX
}
}


Perche' il problema mi sorge con la stosd, visto che con la mia funzione in c dentro ad EDI c'e' 0..

In pascal

function GetCPUID : TCPUID; assembler; register;

TCPUID, assembler, register cosa sono? i valori passati alla funzione? :confused:
Oppure TCPUID e' il valore ritornato?

ceccus
08-12-2004, 15.37.03
Salve,
Allora, tutte le funzioni che vuoi Te le puoi utilizzare utilizzando la chiaamta alla funzione GETOBJECT, per esempio in questo modo :

Dim BiosSet As SWbemObjectSet
Dim bios As SWbemObject
Set BiosSet = GetObject("winmgmts:{impersonationLevel=impersonate}"). _
InstancesOf("Win32_BIOS")
For Each bios In BiosSet
txt = bios.SerialNumber <---- S.N. del bios
Next

Quello che ti ho scritto è in VB6...ma in C++ non cambia di molto....
Stessa cosa per la CPU.....da chiamare nello stesso modo cambiando alcuni parametri :

Dim cpuSet As SWbemObjectSet
Dim cpu As SWbemObject

Set cpuSet = GetObject("winmgmts:{impersonationLevel=impersonate}"). _
InstancesOf("Win32_Processor")
For Each cpu In cpuSet
txt = cpu.PNPDeviceID
Next

Nel progetto vanno inserite le referencez a questi 2 oggetti :
WMIExtension
WMICntl

Ciao !!

pholcus
08-12-2004, 17.41.02
Il problema e' che sto usando C++ BUilder della borland..

Ho gia' provato ad usare WMI ma non compila..

ceccus
08-12-2004, 17.47.33
Salve,
Utilizza il C++ di Visual Studio....vedrai come compili "a bomba"....

Ciao !!

pholcus
08-12-2004, 18.01.55
:rolleyes:

A parte il fatto che vc++ non usa c++ standard, e pasticcia su molte cose..


Secondo te un progetto di qualche migliaio di righe di codice mi metto a riscriverlo per VC++ ?

ceccus
08-12-2004, 18.11.04
Salve,
Non entro nel merito dei "pasticci"...e non posso neppure sapere se il TUO progetto è di 10 righe o di 20.000 righe di codice.....
Daltronde, la GetObject e le librerie WMI sono "incastonate" in Windows (sempre che tu utilizzi tale S.O.) e utilizzando altri Ambienti di Sviluppo diversi da Visual Studio , è facile incappare nelle problematiche in cui sei finito....anche perchè, certe funzionalità, sono veramente a "basso livello".....

Ciao !!

LoryOne
08-12-2004, 19.15.24
Molto probabilmente STOSD è un istruzione non compresa nel set di istruzioni assembly che C++ di Borland ti da la possibilità di utilizzare nel codice inline.

Ad ogni modo, TCPUID è un array di 4 elementi di tipo longint ed è specificata qui:
type
TCPUID = array[1..4] of Longint;

Ho trovato un altro codice in rete http://www.arson-network.com/index.php?class=tutorial&subargs=626 che evita STOSD e DW 0xA20F.
Prova a vedere se funziona ma occhio che se a te serve una funzione ti rimando alla guida di C++ Builder per quanto riguarda il preservare i giusti registri e lo stack prima di procedere alla stesura del codice della funzione onde evitare spiacevoli inconvenienti durante l'esecuzione.
Facci sapere...

LoryOne
08-12-2004, 19.35.34
CPUID è un'istruzione che puoi richiamare solo su processori che la supportano, ecco perchè prima è necessario controllare che si possa richiamare.
A quanto pare, CPUID compila da solo i registri estesi BX,CX e DX e la chiamata a STOSD compila ogni singolo elemento dell'array prelevandolo dall'accumulatore.

pholcus
08-12-2004, 19.50.41
Allora, dalle prove che ho fatto, compilando il codice pascal da c++ builder, funziona tranquillamente..quindi STOSD cosi come STOSB sono istruzioni valida..

Ho sbagliato allora ad implementare le l'asm in c++..

Per quanto riguarda il supporto dei processori, chiamo la funzione in asm presa dal codice pascal e funziona..

ecco un codice di esempio:


#include <stdio.h>

#define ID_BIT 0x200000 // EFLAGS ID bit
long int TCPUID[4];
char TVendor[12];

cpu(void);

int main(int argc, char* argv[])
{
cpu();
return 0;
}
//---------------------------------------------------------------------------


bool IsCPUID_Available(){

asm{
PUSHFD
POP EAX
MOV EDX,EAX //;{save current flags}
XOR EAX,ID_BIT //;{not ID bit}
PUSH EAX //; {onto stack}
POPFD // ;{from stack to flags, with not ID bit}
PUSHFD //; {back to stack}
POP EAX //; {get back to EAX}
XOR EAX,EDX //;{check if ID bit affected}
JZ @exit // ;{no, CPUID not availavle}
MOV AL,1 //;{Result=True}
@exit:
}
}

long int GetCPUID(){
asm {
PUSH EBX //;{Save affected register}
PUSH EDI
MOV EDI,EAX //;{@Resukt}
MOV EAX,1
DW 0xA20F //;{CPUID Command}
STOSD //; {CPUID[1]}
MOV EAX,EBX
STOSD //;{CPUID[2]}
MOV EAX,ECX
STOSD //;{CPUID[3]}
MOV EAX,EDX
STOSD //;{CPUID[4]}
POP EDI //; {Restore registers}
POP EBX
}
}

char GetCPUVendor(){
asm {
PUSH EBX // ; {Save affected register}
PUSH EDI
MOV EDI,EAX // ; {@Result (TVendor)}
MOV EAX,0
DW 0xA20F // ; {CPUID Command}
MOV EAX,EBX
XCHG EBX,ECX // ; {save ECX result}
MOV ECX,4
@1:
STOSB
SHR EAX,8
LOOP @1
MOV EAX,EDX
MOV ECX,4
@2:
STOSB
SHR EAX,8
LOOP @2
MOV EAX,EBX
MOV ECX,4
@3:
STOSB
SHR EAX,8
LOOP @3
POP EDI // ; {Restore registers}
POP EBX
}
}

cpu(){

for (int i=0;i<4 ; i++){
TCPUID[i]=-1;
}
if (IsCPUID_Available()){
GetCPUID();

// printf("TCPUID[0] = %x\n" ,TCPUID[0]);
// printf("TCPUID[1] = %x\n" ,TCPUID[1]);
// printf("TCPUID[2] = %x\n" ,TCPUID[2]);
// printf("TCPUID[3] = %x\n" ,TCPUID[3]);

GetCPUVendor();
//printf("Vendor: %s\n",TVendor);
}

}

LoryOne
09-12-2004, 10.07.57
Benissimo, vuol dire che se compila non è questione di istruzioni assembly.
Prima di tutto:
IsCPUID_Available() cosa ti da come risultato ?
Dovrebbe darti 1, ossia ritornare il valore di AL.
Nel codice Pascal tale valore viene assegnato come valore di ritorno alla funzione stessa.

pholcus
09-12-2004, 12.36.47
Iscpuvailable ritorna 1..

L'esecuzione si blocca sempre su STOSD o STOSB :wall:

su un sito ho trovato la traduzione in c++ della prima funzione senza usare STOSD e funziona..

definendo
typedef unsigned long DWORD;



if (IsCPUID_Available()){
DWORD CPUID1, CPUID2, CPUID3, CPUID4;

asm{
pushad
mov eax, 1
cpuid
mov CPUID1, eax
mov CPUID2, ebx
mov CPUID3, ecx
mov CPUID4, edx
popad
}
printf("%.8X\n", CPUID1);
printf("%.8X\n", CPUID2);
printf("%.8X\n", CPUID3);
printf("%.8X\n", CPUID4);
}


Effettivamente cosi funziona..anche se avrei preferito usare una funzione che mi ritorna i valori..

Ora mi servirebbe convertire la seconda funzione :(

LoryOne
09-12-2004, 18.39.35
Prova così: (vecchio metodo)


char cpusignature[12];
char *t = cpusignature;
asm
{
xor eax, eax
cpuid
// Inserisce la stringa in cpusignature
mov edi, t
mov dword ptr [edi], ebx
mov dword ptr [edi+4], edx
mov dword ptr [edi+8], ecx
// Aggiunge il carattere nullo
mov byte ptr [edi+12], 0
}

Ora cpusignature contiene la stringa del costruttore

pholcus
09-12-2004, 19.19.40
(L) (L) (L)

:grin: :grin: :grin:


Grandissimo!!!

Funziona perfettamente :)

Non so come ringraziarti :)

Per il bios intanto ho trovato una utility da cui si puo trarre spunto che segna tutti gli indirizzi utili..l'ho messa qui:

http://s2000.altervista.org/files/rbe.rar

e anche una guida dettagliata..

http://www.dmtf.org/standards/smbios/

Con un po di lavoro si dobrebbe riuscire a recuperare il seriale..