Mit CPUID die Prozessor Modell Nummer auslesen
-
Hallo so müsste ich ja eigentlich laut Intel Manuel die Prozessor Modell Nummer auslesen können.
Als Ausgabe in EAX bekomme ich hier immer 10.
mov eax,1 cpuid and eax,11110000b
Das Programm CPUID sagt das meine Modell Nummer 1 ist.
Und in einem Beispiel Code habe ich gesehen das nach and eax,11110000b noch ein shr eax,4 kommt. Dann bekomme ich am Ende auch in EAX eine 1 heraus.Aber warum muss man da nochmal rum shiften?
Davon steht nichts in den Intel Manuals. _
-
cpuid schrieb:
Davon steht nichts in den Intel Manuals.
In den Intel Manuals steht, welche Bits von EAX mit welchen Werten gefüllt werden. Intel geht davon aus, dass Du weißt, wohin Du sie shiften musst, um an die Einzelheiten zu gelangen.
Wenn Du den vollständigen Quelltext Deines Programms postest, noch Betriebssystem und Compiler/Assembler mitteilst, dann könnte ich versuchen, Dir die Binärlogik mithilfe eines Programms näher zu bringen.
viele grüße
ralph
-
Weißt du eigentlich, was der "and eax,F0" Befehl genau macht?
(und wie man die Binärnummern zur Ausgabe bekommt?)
-
Assembler: MASM
OS: Windows XPUnd ja ich weiss was der and Befehl macht. Aber ich weiss nicht woher man wissen soll das man hier shiften muss anstatt Intel das mit ins Manuel reinschreiben ...
.686p .model flat, stdcall option casemap :none include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib include \masm32\include\masm32.inc includelib \masm32\lib\masm32.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib .data nr dd 0,0 .code start: mov eax,1 cpuid and eax,11110000b shr eax,4 add eax,30h mov dword ptr [nr] ,eax invoke StdOut, addr nr invoke Sleep,1000 invoke ExitProcess,0 end start
-
cpuid schrieb:
... anstatt Intel das mit ins Manuel reinschreiben ...
Im Manual steht noch sowas wie "see Figure 3-5 oder 3-6 oder so" :
in EAX = 1 out EAX : bitnr: 00-03 Stepping ID 04-07 Model 08-11 Family ID 16-19 Extended Model ID 20-27 Extended Family ID
-
rkhb schrieb:
Wenn Du den vollständigen Quelltext Deines Programms postest, noch Betriebssystem und Compiler/Assembler mitteilst, dann könnte ich versuchen, Dir die Binärlogik mithilfe eines Programms näher zu bringen.
cpuid schrieb:
Assembler: MASM
OS: Windows XPNun denn, hier erstmal das Programm zur (späteren) Erklärung:
.686p .model flat, stdcall option casemap :none include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib .DATA lfd db "1) "; hex db "0123456789ABCDEF" buf db "-",10 .DATA? hStdOut dd ? bin db 40 DUP (?) int32 dd ? NumberOfBytesWritten dd ? .CODE int2bin PROC int2bin ENDP Int2Bin PROC ; http://dcla.rkhb.de/umwandlung/int2bin.html pushad mov edx,[int32] ; Integer mov edi, OFFSET bin ; Binärzahl (Puffer muss jetzt 40 Bytes fassen können) mov ecx,8 ; äußere Schleife: 8 Nibbles Schleife1: push ecx mov ecx,4 ; innere Schleife: 4 Bits Schleife2: shl edx,1 setc al ; AL je nach herausgeschobenen Bit setzen or al,30h ; ASCII stosb ; und in bin abspeichern loop Schleife2 ; innere Schleife mov al,32 ; Leerzeichen stosb pop ecx ; äußere Schleife loop Schleife1 mov byte ptr [edi-1],10 ; \n ersetzt letztes Leerzeichen popad ret Int2Bin ENDP WriteBin PROC pushad invoke WriteFile, DWORD PTR [hStdOut], ADDR lfd, 4, ADDR NumberOfBytesWritten, 0 add BYTE PTR [lfd], 1 invoke WriteFile, DWORD PTR [hStdOut], ADDR bin, 40, ADDR NumberOfBytesWritten, 0 popad ret WriteBin ENDP WriteChar PROC pushad invoke WriteFile, DWORD PTR [hStdOut], ADDR lfd, 4, ADDR NumberOfBytesWritten, 0 invoke WriteFile, DWORD PTR [hStdOut], ADDR buf, 2, ADDR NumberOfBytesWritten, 0 popad ret WriteChar ENDP main PROC invoke GetStdHandle, STD_OUTPUT_HANDLE mov DWORD PTR [hStdOut], eax mov eax,1 ; Funktionsnummer für CPUID mov dword ptr [int32], eax call Int2Bin call WriteBin ; 1) binäre Ausgabe der Funktionsnummer cpuid mov dword ptr [int32], eax ; Ergebnis von CPUID call Int2Bin call WriteBin ; 2) binäre Ausgabe des Ergebnisses von CPUID mov edx, 11110000b ; AND-Maske mov dword ptr [int32], edx call Int2Bin call WriteBin ; 3) binäre Ausgabe der AND-Maske and eax, 11110000b ; CPUID-Ergebnis undieren mov dword ptr [int32], eax call Int2Bin call WriteBin ; 4) binäre Ausgabe des Ergebnisses der AND-Operation shr eax,4 ; nach rechts, um es besser umwandeln zu können mov dword ptr [int32], eax call Int2Bin call WriteBin ; 5) binäre Ausgabe des Ergebnisses der Shift-Operation mov ebx, OFFSET hex xlat ; in Hexziffer(ASCII) umwandeln mov BYTE PTR [buf] ,al call Int2Bin call WriteChar ; 6) Ausgabe der Hexzahl invoke ExitProcess,0 ; und tschüss. main ENDP END main
Die Ausgabe des Programms sieht bei mir folgendermaßen aus:
`-
0000 0000 0000 0000 0000 0000 0000 0001
-
0000 0000 0000 0000 0000 0110 1111 1011
-
0000 0000 0000 0000 0000 0000 1111 0000
-
0000 0000 0000 0000 0000 0000 1111 0000
-
0000 0000 0000 0000 0000 0000 0000 1111
-
F
`
- Zunächst ist wichtig, dass Du Dir ein Register (EAX, EBX, ECX, EDX) nur als ein Bündel von 32 Bits vorstellst. Ob diese 32 Bit nun ein Buchstabe, eine Zahl, eine Adresse oder was ganz anderes darstellen soll, bestimmt der Programmierer (manchmal ist seine Wahl ein bisschen eingeschränkt, aber das ist hier nicht wichtig). Als erstes füllst Du EAX mit einer Funktionsnummer für CPUID (mov eax,1). Wie die 32 Bits von EAX danach aussehen, erzählt Dir die Zeile 1) des Programms.
Die 32 Bits von EAX werden von rechts nach links durchnummeriert. Die '1' ganz rechts, trägt also die Bezeichnung Bit0 und die '0' ganz links heißt Bit31 (Bit0 bis Bit31 ergibt 32 Bits).
- Nun wird CPUID aufgerufen. Die CPU guckt nach der Funktionsnummer und gibt ein Ergebnis in EAX aus. Wie das aussieht, erzählt Dir Zeile 2) des Programms. Nun musst Du in das Manual Deiner CPU gucken, um zu erfahren, was das bedeuten soll. Wenn Du einen Intel-Prozessor hast, guckst Du in das Intel-Manual, wenn Du einen AMD-Prozessor, guckst Du in das AMD-Manual. Das liegt daran, dass sich die CPUID-Ausgaben der verschiedenen Prozessoren unterscheiden können.
Das zuständige Intel-Manual heißt "Intel
64 and IA-32 Architectures Software Developer's Manual Combined Volumes 2A, 2B, and 2C: Instruction Set Reference, A-Z" (http://www.intel.de/content/www/de/de/processors/architectures-software-developer-manuals.html). Hier stehen alle Informationen in Kapitel 3.2 (Instructions A-L) unter "CPUID - CPU Identification". Auf Table 3.17 steht, dass bei einem Initial Value von EAX=01H in EAX "Type, Family, Model, and Stepping ID (see Figure 3-5)" ausgegeben wird. Figure 3-5 befindet sich recht viek weiter unten und teilt Dir mit, welche Informationen in welchen Bits von EAX landen. Die kleinen Zahlen oben sind die Bitnummerierung.
-
Dich interessiert die Information "Model", die sich nach Figure 3-5 an Bit4 bis Bit7 befindet. Wenn Du jetzt in Zeile 2) des Programms von rechts abzählst (mit Null beginnend), dann siehst Du, dass es sich um den zweiten Vier-Block von rechts handelt. Alles übrige interessiert Dich nicht. Dieses "übrige" wird jetzt brutal auf Null gesetzt, damit es keine Verwirrung stiften kann. Dazu dient der AND-Befehl. Nur wo in Zeile 3) eine '1' steht, wird der Inhalt von Zeile 2) durchgelassen und erscheint in Zeile 4).
-
In Zeile 4) hast Du nur noch einen Block mit Information, das ist der zweite von rechts. Alle anderen Blöcke mit jeweils 4 Bits sind auf Null gesetzt. Jetzt kommt das, was Intel beim besten Willen nicht wissen kann, nämlich was Du mit diesem Block anstellen willst. Du willst offenbar, dass der Inhalt des Blocks als Zahl ausgegeben wird. Mit vier Bits kann man eine Zahl von 0 bis 15 darstellen, einfacher zu programmieren ist eine Hex-Zahl von 0 bis F. Mit dem Befehl XLAT wird jeweils ein Buchstabe (ASCII) aus dem String hex="0123456789ABCDEF" geholt, und zwar jeweils die Stelle, die in AL steht (ab Null zählend). Steht also in AL eine 6, dann wird die 7. Ziffer geholt - das ist die '6' - und in AL gespeichert. Aber wie kommt man zu so einem Wert in AL, die Model-Nummer in EAX steht doch ganz woanders?
-
Die Modelnummer muss nach rechts. Das Ergebnis siehst Du in Zeile 5) des Programms. Nun haben wir in AL eine Bitfolge, die man als Zähler (Index) für XLAT gebrauchen kann.
-
Nach dem Shift-Befehl steht Model in AL und mit dem XLAT-Befehl wird der Wert in AL in eine ASCII-Hexadezimalziffer umgewandelt. Das Ergebnis wird in Zeile 6) ausgegeben.
viele grüße
ralphP.S.: Da wir hier nicht in einem Chat sind (und ich deshalb auch für Lurker und Googler schreibe), wirst Du nicht aufschreien "Das habe ich doch schon längst alles seit Jahren gewusst!!!", sondern Dir überlegen, welchen Denkfehler Du auf Intel abschieben willst.
-