|
Muetze1
(Gast)
n/a Beiträge |
#19
Moin!
![]() Ok, ich ändere den Code mal schnell... @other: Falls ihr den Code schon genutzt habt, If Bedingung 2x ändern (ja ja Copy&Paste) oder nochmals neu kopieren und einfügen... /EDIT: Ok, ändern geht nicht mehr in diesem Forum und dafür den Mod belästigen muss nicht sein, daher jetzt der funktionierende Code...
Delphi-Quellcode:
Ich habe den Code gleich mal ein wenig kommentiert, damit kommt vielleicht ein wenig Klarheit auf über das was ich da überhaupt mache...
Unit L2Cache;
Interface Function GetL2CacheSize : String; Implementation uses sysutils; // prüfen, ob die CPU die CPUID Instruktion unterstützt // // Anmerkung: Bei Cyrix M2 CPU's muss man die Instruktion vorher in einem // Cyrix spezifischen Register enablen, sonst ist sie unbekannt // und die EFlags verhalten sich dem entsprechend. In diesem Falle // ist das aber hinfällig, da Cyrix CPU's keine Cache Informationen // über CPUID zurückliefern sondern nur über ihre Configuration // Register auf Port $FE und $FF... Function CheckForCPUID : Boolean; Assembler; Asm push ebx push ecx pushfd // save EFLAGS pop eax // store EFLAGS in EAX mov ebx, eax // save in EBX for later testing xor eax, 00200000h // toggle bit 21 push eax // put to stack popfd // save changed EAX to ELFAGS pushfd // push EFLAGS on stack pop ecx // store EFLAGS in EAX mov Result, False cmp ecx, ebx // see if bit 21 has changed jz @@no_CPUID // if no change, no CPUID mov Result, True // set flag @@no_CPUID: pop ecx pop ebx End; Function GetL2CacheSize : String; Var CPUID_VendorID : Array[0..11] Of Char; // für den Vendor-String MaxStdLevel, // höchstes CPUID Standardlevel MaxExtLevel : LongWord; // höchstes CPUID erweitertes Level // Unterfunktion für Intel CPU's Function GetIntelCacheInfo : String; Var CallCtr : Byte; // gibt an, wie oft CPUID 02h aufgerufen // werden muss, um alle Cache Info's zu // bekommen Regs : array[0..3] Of LongWord; // Speicher für die Register nach CPUID 02h i : Integer; // Zählvariable KBSize : Word; // die Grösse des L2 Caches in KByte // die Intel CPU's geben in mehreren Byte Werten ihre Info's an, und // es kann mehrere ID's für den selben Cache Typ geben, daher hier anhand // der ID die Grösse zurückgeben oder 0, wenn es kein L2 Cache Deskriptor war Function CacheInfo(CacheID : Byte): Word; Begin Case CacheID Of $39, $3B, $41, $79 : Result := 128; $3C, $42, $7A, $82 : Result := 256; $43, $7B, $83, $86 : Result := 512; $44, $7C, $84, $87 : Result := 1024; $85, $45 : Result := 2048; Else Result := 0; End; End; // ok, ans eingemachte für die Intel Cache Info's Begin Asm push eax // register sichern - alle - auch wenn in der Delphi Hilfe push ebx // steht, das man einzelne Register frei verändern darf. push ecx // Diese Aussage trifft nur bei nicht optimierte Codes zu, wenn push edx // die Optimierung an ist (default), dann fällt Delphi dadurch // gerne auf die Schnauze... mov eax, 2 // Funktion laden (hier: 0000.0002h) db 00fh, 0a2h // CPUID mov CallCtr, al // CallCtr merken mov Regs[0].longword, eax // Register sichern zum auswerten mov Regs[1].longword, ebx mov Regs[2].longword, ecx mov Regs[3].longword, edx pop edx // Register wiederherstellen, damit Delphi keine Problem bekommt pop ecx pop ebx pop eax End; // CallCtr lass ich mal aussen vor, wird bisher noch nicht benutzt von Intel // (also noch nicht > 1) // ok, dann zählen wir mal die KBytes zusammen der einzelnen Deskriptoren KBSize := 0; If ( Regs[0] And $80000000 ) = 0 Then // prüfen ob gültige Angabe Begin If ( ( Regs[0] Shr 8 ) And $ff ) > 0 Then // wenn was drinne steht ... Inc(KBSize, CacheInfo(( Regs[0] Shr 8 ) And $ff)); // ... dann auswerten If ( ( Regs[0] Shr 16 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[0] Shr 16 ) And $ff)); If ( ( Regs[0] Shr 24 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[0] Shr 24 ) And $ff)); End; // da in EAX der CallCtr mit drinne steht, wird das hier drüber extra behandelt // und die restlichen können wir in einem Rutsch durchgehen For i := 1 To 3 Do Begin If ( Regs[i] And $80000000 ) = 0 Then Begin If ( ( Regs[i] Shr 8 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[i] Shr 8 ) And $ff)); If ( ( Regs[i] Shr 16 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[i] Shr 16 ) And $ff)); If ( ( Regs[i] Shr 24 ) And $ff ) > 0 Then Inc(KBSize, CacheInfo(( Regs[i] Shr 24 ) And $ff)); End; End; // Ausgabe bilden If ( KBSize < 1024 ) Then // noch im KByte Bereich? Result := IntToStr(KBSize) + ' KB' // ok, dann KByte Else Result := IntToStr(KBSize Div 1024) + ' MB'; // nein, also MByte End; // ok, gleiches für AMD Function GetAMDCacheInfo : String; Var KBSize : Word; Begin // AMD macht es uns einfacher, die haben direkt eine Angabe des L1 und L2 // Cache-Grösse in KByte als Rückgabewert Asm push eax // siehe oben push ebx push ecx push edx mov eax, 080000006h // Funktionsnummer laden (hier: 8000.0006h) db 00fh, 0a2h // CPUID shr ecx, 16 // in Bits 16..31 steht die Grösse in KByte mov KBSize, cx // daher: runterschieben und die 16 Bits merken pop edx pop ecx pop ebx pop eax End; // Ausgabe bilden - same procedure as every cpu... ;-) If ( KBSize < 1024 ) Then Result := IntToStr(KBSize) + ' KB' Else Result := IntToStr(KBSize Div 1024) + ' MB'; End; Begin // ok, hier gehts los If ( CheckForCPUID ) Then // haben wir überhaupt eine Chance, oder anders: Begin // bietet die CPU einen CPUID Befehl? Asm push eax // wieder Register sichern... push ebx push ecx push edx // xor eax, eax setzt eax auf 0 - laut AMD Optimizing Doc ist mov eax, 0 // schneller beim AMD. Laut Intel ist xor eax, eax schneller bei Intel... xor eax, eax // Funktionsnummer laden (hier: 0000.0000h) db 00fh, 0a2h // CPUID // in EAX steht das höchste Standard CPUID Level -> merken mov MaxStdLevel, eax // wir wollen den Vendor String speichern - und das geht am einfachsten // mit den String Befehlen der CPU... push edi // enhanced destination index = Zieladresse // vorher aber erstmal sichern... lea edi, CPUID_VendorID // dann die Adresse der Variablen holen cld // direction flag löschen, wir wollen EDI erhöhen... mov eax, ebx // als erstes muss der Inhalt von EBX gespeichert // werden, und da SToreStringDword immer EAX // schreibt, muss EBX in EAX gepackt werden... stosd // ok, schreiben mov eax, edx // gleiches mit EDX stosd // und hinten ranhängen // (EDI ist jetzt schon auf CPUID_VendorID[4]) mov eax, ecx // gleiches mit ECX stosd pop edi // ok, Inhalt von EDI wiederherstellen // auf erweiterten CPUID testen mov eax, 080000000h // Funktionsnummer laden (hier: 8000.0000h) db 00fh, 0a2h // CPUID mov MaxExtLevel, eax // maximale Funktionsnummer sichern... pop edx // Register wiederherstellen pop ecx pop ebx pop eax End; // nun gehts an die Auswertung und da kocht jeder Hersteller sein eigenes // Süppchen... If ( String(CPUID_VendorID) = 'GenuineIntel' ) Then // Intel Begin If ( MaxStdLevel >= 2 ) Then // wir brauchen min. CPUID 0000.0002h Result := GetIntelCacheInfo Else Result := 'unkown'; End Else If ( String(CPUID_VendorID) = 'AuthenticAMD' ) Then // AMD Begin // wir brauchen min. CPUID 8000.0006h If ( MaxExtLevel >= $80000006 ) Then // ab K6-III Result := GetAMDCacheInfo Else Result := 'unkown'; End Else If ( String(CPUID_VendorID) = 'CyrixInstead' ) Then Begin // tja, die Cyrix'e - keine Cache Info im CPUID, alles per Cyrix // specific Register... Result := 'no cache info'; End; // Transmeta und weitere erstmal wegfallen lassen... End Else Result := 'no CPUID support'; End; End. MfG Muetze1 |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |