Cpuid : des informations sur votre processeur (intel et amd)

Soyez le premier à donner votre avis sur cette source.

Vue 10 501 fois - Téléchargée 711 fois

Description

Ce code permet gràce à l'instruction ASM CPUID de déterminer le type de processeur, sa description et diverses informations sur ses caches,...

Ce code est aussi la base de ma source CPUID (la dll) sur vbfrance.com

Pour avoir un aperçu de la sortie de cpuid, regarder la capture

Testé avec un AMD sur 98/XP

Source / Exemple :


//ce code n'est pas la totalité de la source
// ProcessorInfo.cpp : définit le point d'entrée pour l'application DLL.
//

//#include "stdio.h"
#include "ProcessorInfo.h"

//Teste si CPUID est présent
BOOL WINAPI IsCPUIDAvailable()
{
	//premiere méthode
	/*__asm {
		PUSH EBX
		PUSHFD
		POP EAX
		MOV EBX,EAX
		XOR EAX,0x00200000
		PUSH EAX
		POPFD
		PUSHFD
		POP EAX
		CMP EAX,EBX
		JE unsupported
		XOR EAX,EAX
		MOV EAX,1
		JMP fin
		
unsupported:
		XOR EAX,EAX

fin:
		POP EBX
	}*/
	//seconde méthode
	__try
	{
		__asm{
			XOR EAX,EAX
			XOR EBX,EBX
			XOR ECX,ECX
			XOR EDX,EDX
			CPUID
		}
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
		return FALSE;
	}
	return TRUE;
}

//retourne la valeur max de EAX pour CPUID
//ou 0 si CPUID n'est pas présent
_declspec(naked) DWORD WINAPI GetMaxCPUIDValue()
{
	//DWORD dwMaxCPUIDValue=0;
	//if (IsCPUIDAvailable()==TRUE)
	//{
		__asm {
			PUSH EBP
			MOV EBP,ESP
			CALL IsCPUIDAvailable
			TEST EAX,EAX
			JE No_CPUID

			PUSH EBX
			XOR EAX,EAX
			XOR EBX,EBX
			XOR ECX,ECX
			XOR EDX,EDX
			CPUID //0
			//MOV dwMaxCPUIDValue,EAX
			POP EBX
			POP EBP
			RET
No_CPUID:
			XOR EAX,EAX
			POP EBP
			RET
	}
	//}
	//return dwMaxCPUIDValue;
}

//retourne la valeur maximum de EAX pour CPUID extended
//ou 0 si CPUID n'est pas présent
_declspec(naked) DWORD WINAPI GetMaxCPUIDExtendedValue()
{
	//DWORD dwMaxCPUIDExValue=0;
	//if (IsCPUIDAvailable()==TRUE)
	//{
		__asm {
			PUSH EBP
			MOV EBP,ESP
			CALL IsCPUIDAvailable
			TEST EAX,EAX
			JE No_CPUID

			PUSH EBX
			XOR EAX,EAX
			XOR EBX,EBX
			XOR ECX,ECX
			XOR EDX,EDX
			MOV EAX,0x80000000
			CPUID //0x80000000
			//MOV dwMaxCPUIDExValue,EAX
			POP EBX
			POP EBP
			RET
No_CPUID:
			XOR EAX,EAX
			POP EBP
			RET
	}
	//}
	//return dwMaxCPUIDExValue;
}

_declspec(naked) BOOL WINAPI GetCPUVendorID(char* lpszVendorID,DWORD* lpdwMaxCPUIDValue)
{
//	DWORD REGEBX,REGECX,REGEDX;
//	if (IsCPUIDAvailable()==TRUE)
//	{
		__asm {
			PUSH EBP
			MOV EBP,ESP
			CALL IsCPUIDAvailable
			TEST EAX,EAX
			JE No_CPUID

			PUSH EBX
			XOR EAX,EAX
			XOR EBX,EBX
			XOR ECX,ECX
			XOR EDX,EDX
			CPUID //0
			//copie les données
			PUSH EDI
			MOV EDI,[lpdwMaxCPUIDValue]
			MOV [EDI],EAX
			//MOV REGEBX,EBX
			//MOV REGECX,ECX
			//MOV REGEDX,EDX
			CMP [lpszVendorID],0
			JE No_CPUID
			MOV EDI,[lpszVendorID]
			MOV [EDI],EBX
			MOV [EDI+4],EDX
			MOV [EDI+8],ECX
			MOV [EDI+12],0
			MOV EAX,1
			POP EDI
			POP EBX
			POP EBP
			RET 8
No_CPUID:
			XOR EAX,EAX
			POP EBP
			RET 8
	}
		//si le tampon passé à la fontion est correcte
		//if (lpszVendorID)
		//{
			//on copie la chaine
			//CopyMemory(lpszVendorID,&REGEBX,4);
			//CopyMemory(lpszVendorID+4,&REGEDX,4);
			//CopyMemory(lpszVendorID+8,&REGECX,4);
			//lpszVendorID[12]=0;
		//}
		//return TRUE;
	//}
	//else
	//{
	//	return FALSE;
	//}
}
//renvoie les caractéristiques standards
_declspec(naked) BOOL WINAPI GetProcessorStdFeatures(DWORD* FeatureFlags)
{
	//if (IsCPUIDAvailable()==TRUE)
	//{
		//CPUID 1
		//if (GetMaxCPUIDValue() >= 1)
		//{
			__asm {
				PUSH EBP
				MOV EBP,ESP
				CALL IsCPUIDAvailable
				TEST EAX,EAX
				JE No_CPUID
				
				CALL GetMaxCPUIDValue
				CMP EAX,1
				JB No_CPUID

				PUSH EBX
				XOR EAX,EAX
				XOR EBX,EBX
				XOR ECX,ECX
				XOR EDX,EDX
				MOV EAX,1
				CPUID //1
				//on copie les données
				MOV EAX,[FeatureFlags]
				MOV [EAX],EDX
				POP EBX
			MOV EAX,1
			POP EBP
			RET 4
No_CPUID:
			XOR EAX,EAX
			POP EBP
			RET 4
			}
/*			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
	else
	{
		return FALSE;
	}*/
}

//renvoie la signature du prcesseur
BOOL WINAPI GetProcessorSignature(Signature* ProcSignature)
{
//#pragma warning (disable : 4244)
	DWORD REGEAX,REGEBX;
	if (IsCPUIDAvailable()==TRUE)
	{
		//CPUID 1
		if (GetMaxCPUIDValue() >= 1)
		{
			__asm {
				PUSH EBX
				XOR EAX,EAX
				XOR EBX,EBX
				XOR ECX,ECX
				XOR EDX,EDX
				MOV EAX,1
				CPUID //1
				//on copie les données
				MOV REGEAX,EAX
				MOV REGEBX,EBX
				POP EBX
			}
			//si le tampon passé est correct
			if (ProcSignature)
			{
				//on met en forme les données
				ProcSignature->SteppingID = (REGEAX & 0x0000000F);
				ProcSignature->ModelNumber = ((REGEAX>>4) & 0x0000000F);
				ProcSignature->FamilyCode = ((REGEAX>>8) & 0x0000000F);
				ProcSignature->INTELProcessorType = ((REGEAX>>12) & 0x00000003);
				ProcSignature->ExtendedModel = ((REGEAX>>16) & 0x0000000F);
				ProcSignature->ExtendedFamily = ((REGEAX>>20) & 0x000000FF);

				ProcSignature->BrandID = (REGEBX & 0xF);
				ProcSignature->CLFLUSHLineSize = ((REGEBX>>8) & 0xF);
				ProcSignature->CountOfLogicalProcessors = ((REGEBX>>16) & 0xF);
				ProcSignature->APICID = ((REGEBX>>24) & 0xF);
			}

				return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
	else
	{
		return FALSE;
	}
}

//renvoie le nom du processeur
BOOL WINAPI GetProcessorNameString(char* lpszProcName)
{
	DWORD REGEAX,REGEBX,REGECX,REGEDX;
	if (IsCPUIDAvailable()==TRUE)
	{
		//CPUID 0x80000004
		if (GetMaxCPUIDExtendedValue() >=4)
		{
			for (DWORD i=2;i<4;i++)
			{
				_asm {
					PUSH EBX
					XOR EAX,EAX
					XOR EBX,EBX
					XOR ECX,ECX
					XOR EDX,EDX
					MOV EAX,0x80000000
					OR EAX,i
					CPUID //0x80000004
					//on copie les données
					MOV REGEAX,EAX
					MOV REGEBX,EBX
					MOV REGECX,ECX
					MOV REGEDX,EDX
					POP EBX
				}
				//si le tampon est correcte
				if (lpszProcName)
				{
					//on copie le nom dans le tampon
					CopyMemory(lpszProcName + (i-2) * 16,&REGEAX,4);
					CopyMemory(lpszProcName + (i-2) * 16 + 4,&REGEBX,4);
					CopyMemory(lpszProcName + (i-2) * 16 + 8,&REGECX,4);
					CopyMemory(lpszProcName + (i-2) * 16 + 12,&REGEDX,4);
					REGEAX=REGEBX=REGECX=REGEDX=0;
				}
			}
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
	else
	{
		return FALSE;
	}
}

//permet de connaitre les résultats dans les registres du processeur suite à un CPUID
_declspec(naked) BOOL WINAPI GetCPUIDResult(DWORD* REGEAX,DWORD* REGEBX,DWORD* REGECX,DWORD* REGEDX)
{
/*	if (IsCPUIDAvailable() == TRUE)
	{*/
		_asm {
			PUSH EBP
			MOV EBP,ESP
			CALL IsCPUIDAvailable
			TEST EAX,EAX
			XOR EAX,EAX
			JE No_CPUID

			PUSH EBX
			PUSH EDI
			XOR EAX,EAX
			XOR EBX,EBX
			XOR ECX,ECX
			XOR EDX,EDX
			//on copie REGEAX dans EAX
			MOV EAX,[REGEAX]
			MOV EAX,[EAX]
			//on execute CPUID
			CPUID
			//on copie l'adresse de *REGEAX
			MOV EDI,[REGEAX]
			//si le pointeur est nul
			TEST EDI,EDI
			JE Fin
			//on copie EAX dans REGEAX
			MOV [EDI],EAX
			//pareil pour EBX,ECX,EDX
			MOV EDI,[REGEBX]
			TEST EDI,EDI
			JE Fin
			MOV [EDI],EBX
			MOV EDI,[REGECX]
			TEST EDI,EDI
			JE Fin
			MOV [EDI],ECX
			MOV EDI,[REGEDX]
			TEST EDI,EDI
			JE Fin
			MOV [EDI],EDX
FIN:
			MOV EAX,1
No_CPUID:
			POP EDI
			POP EBX
			POP EBP
			RET 16
		}
/*		return TRUE;
	}
	else
	{
		return FALSE;
	}*/
}

Conclusion :


Ce code contient de l'ASM en ligne. Il a été fait avec Visual Studio .Net 2003...

N'hésitez pas à commenter et à noter...

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

BruNews
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
7 novembre 2014
13 -
Pourquoi PUSHAD dans toutes ces fonctions quand tu n'utilises parfois qu'1 seul registre ?
CMP EDI,0 => TEST edi, edi
__declspec(naked) devant les fonctions pour les ecrire en pur asm et gagner pas mal de cycles.
BruNews
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
7 novembre 2014
13 -
Salut ShareVB,
http://www.cppfrance.com/code.aspx?ID=25597
j'ai remis un exemple, bien moins etendu que le tien, tu pourras jeter un oeil si tu veux pour voir comment supprimer CopyMemory et tous les transferts registres-memoire inutiles.
Si tu as des questions, pas de probleme.
ciao...
BlackGoddess
Messages postés
338
Date d'inscription
jeudi 22 août 2002
Statut
Membre
Dernière intervention
14 juin 2005
-
mettre _declspec(naked) et WINAPI ne sont pas contradictoires ?
BruNews
Messages postés
21054
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
7 novembre 2014
13 -
aucunement, WINAPI est un alias de __stdcall.
Par contre, avec 'naked' il ne doit y avoir aucun code 'C', doit commencer par '__asm' et finir a 'ret xxx'.
BlackGoddess
Messages postés
338
Date d'inscription
jeudi 22 août 2002
Statut
Membre
Dernière intervention
14 juin 2005
-
il me semblait que __stdcall définissait une convention d'appel, et que _declspec(naked) supprimait l'en-tete de fonction ... l'implémentation de la convention ne se trouve donc pas dans l'en-tete ? je dois tout mélanger

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.