Wie überprüfen ob eflags vorhanden?
-
Zu erst einmal wünsche ich allen Foren-Usern ein frohes neues Jahr!
Ich habe auch nur eine kleine Frage: Und zwar brauche ich Code, mit dem ich prüfen kann, ob mir Instruktionen von MMX, SSE, SSE2 usw. zur Verfügung stehen. Dies ist alles kein Problem, jedoch muss ich zunächst einmal prüfen ob mir der Pefehl "cpuid" überhaupt zur Verfügung steht.
Dies wiederum mache ich, in dem ich bit 21 (ID-Bit) der eflags überprüfe.Wie kann ich aber sicherstellen, dass die erweiterten Flags überhaupt existieren?
-
Auf die EFLAGS kannst du zugreifen, wenn du einen 386er oder neuer hast. Wenn du im 32-Bit-Modus (z.B. unter Windows, Linux, ...) bist, dann hast du definitiv einen 386er oder neuer. Wenn dir nicht sicher bist, ob du einen 386er oder neuer hast, dann solltest du dir http://www.intel.com/Assets/PDF/appnote/241618.pdf durchlesen. Kapitel 9 enthält einen sehr sehr sehr genauen Beispielcode inklusive Erklärungen...
-
Ja, dass sieht sehr gut aus, danke.
Ich habe aber noch ein kleines Problem bei meinem restlichen Code, ich erhalte immer den Fehlern "unknown 0001", wenn ich meinen Code aus C heraus mit dem Visual Studio 2008 linke.
MASM compiliert ohne Probleme (Parameter -c -coff)Hier der Code:
TITLE sse checking - check for MMX, SSE, SSE2, SSE3, SSSE3 and SSE4.1 support .MODEL SMALL .8086 .DATA ; --------- ; ; constants ; ; --------- ; ID_BIT EQU 00200000h FEATURE_BYTE EQU 1 MMX_BIT EQU 00800000h SSE_BIT EQU 02000000h SSE2_BIT EQU 04000000h SSE3_BIT EQU 00000001h SSSE3_BIT EQU 00000200h SSE41_BIT EQU 00080000h MMX EQU 0 ; MMX Technology Support SSE EQU 1 ; SSE2 EQU 2 ; SSE3 EQU 3 ; SSSE3 EQU 4 ; SSE41 EQU 5 ; ; ---------------- ; ; global variables ; ; ---------------- ; _InstructionSetAvailable db 6 dup(0) ; set to "false" (0) by default _CPUID_Available db 0 ; "" _EFLAGS_Available db 0 ; "" ; --------------- ; ; global routines ; ; --------------- ; PUBLIC _Initialize .CODE _Initialize PROC ; mov ax, @data ; mov ds, ax .386 pushfd ; push eflags to stack pop eax ; load eflags to eax mov edx, eax ; save value in edx xor eax, ID_BIT ; not ID bit push eax ; back to stack popfd ; from stack to eflags with not ID bit pushfd ; push eflags to stack (again) pop eax ; load it to eax xor eax, edx ; check for equality jz SHORT done ; equals? if true cpuid is not available (pre Pentium+) inc BYTE PTR [ds:_CPUID_Available] .586 ; enable Penium-Instructionset (f. CPUID) mov eax, FEATURE_BYTE ; check byte 1 (processor info and feature bits) cpuid test edx, MMX_BIT ; check for MMX Technology support setnz BYTE PTR [ds:_InstructionSetAvailable + MMX] test edx, SSE_BIT ; check for Streaming SIMD Extensions (SSE) support setnz BYTE PTR [ds:_InstructionSetAvailable + SSE] test edx, SSE2_BIT ; check for SSE2 support setnz BYTE PTR [ds:_InstructionSetAvailable + SSE2] test ecx, SSE3_BIT ; check for SSE3 support setnz BYTE PTR [ds:_InstructionSetAvailable + SSE3] test ecx, SSSE3_BIT ; check for Supplemental Streaming SIMD Extensions 3 support setnz BYTE PTR [ds:_InstructionSetAvailable + SSSE3] test ecx, SSE41_BIT ; check for SSE4.1 support setnz BYTE PTR [ds:_InstructionSetAvailable + SSE41] done: ret _Initialize ENDP END
#include <stdio.h> #define BOOL unsigned char #define MMX 0 #define SSE 1 #define SSE2 2 #define SSE3 3 #define SSSE3 4 #define SSE41 5 extern BOOL InstructionSetAvailable[6]; extern void Initialize(); int main() { if( InstructionSetAvailable[SSE3] ) { ... } return 0; }
-
Die Funktion ist nicht idiotensicher - ich blicke da nicht mehr durch
Vielleicht ein Vorschlag: Man könnte die Funktion auf das Ausführen von CPUID und Speichern der EAX...EDX Register vereinfachen, und die ganze Logik, ob MMX, SSE usw., in C implementieren. Ungefähr so// Irgendwie in Assember implementiert: extern int ExecuteCPUID(unsigned int FunctionID, unsigned int *pRegs) ... unsigned int Regs[4]; int err = 0; bool flag_MMX = false; err = ExecuteCPUID(FEATURE_BYTE, &Regs[0]); if (err < 0) { // CPUID not supported ... } else { // Regs[0...3] contains EAX, EBX, ECX, EDX flag_MMX = (MMX_BIT == (Regs[EDX] & MMX_BIT)); ... }
-
abc.w schrieb:
Die Funktion ist nicht idiotensicher - ich blicke da nicht mehr durchmeinerseits
Wo ist das Problem?Ich habe ein array aus 6 Byte, welche bool's entsprechen sollen. So kann ich (wie im C-Code gezeigt) einfach per "InstructionSetAvailable" und dem Offset prüfen, ob ein spezieller Befehlssatz verfügbar ist.
Die Constanten (sowhol in C als auch asm) hab ich zur Vereinfachung gemacht.
Was genau verstehst du da nicht? Rein aus Interesse.
-
FrEEzE2046 schrieb:
.MODEL SMALL .8086
Das sollte vermutlich eher so aussehen
.386 .model flat
schließlich soll keine 16bit-Anwendung erstellt werden.
-
FrEEzE2046 schrieb:
Was genau verstehst du da nicht? Rein aus Interesse.
Ich glaube, ich verstehe die Funktion ganz gut. Finde nur, dass das Auswerten und Setzen der Flags zu viel des Guten ist und man sollte es in C/C++ machen. Ansonsten ist die Funktion gut und geradeaus geschrieben (noch). Ich glaube, man muss jetzt nur noch die Register ECX, EBX und EDX "retten" und wiederherstellen, weil CPUID sie ja überschreibt...
-
camper schrieb:
FrEEzE2046 schrieb:
.MODEL SMALL .8086
Das sollte vermutlich eher so aussehen
.386 .model flat
schließlich soll keine 16bit-Anwendung erstellt werden.
Ähm,
ohne Scheiß. Das habe ich komplett übersehen. Kann dir aber auch sagen woran's liegt:
Ich habe zuvor ein kleines Tool geschrieben, was beim Starten des Computers ausgefehrt werden kann, und da ich mich da im Real-Mode befinde ...
abc.w schrieb:
Ich glaube, ich verstehe die Funktion ganz gut. Finde nur, dass das Auswerten und Setzen der Flags zu viel des Guten ist und man sollte es in C/C++ machen. Ansonsten ist die Funktion gut und geradeaus geschrieben (noch). Ich glaube, man muss jetzt nur noch die Register ECX, EBX und EDX "retten" und wiederherstellen, weil CPUID sie ja überschreibt...
Ja, ich weiß was du meinst. Aber 1. hab ich mit der Funktion nichts weiter vor, als dieses Array zu setzen und 2. wird der Code in dem die Funktion "eigentlich" aufgerufen wird, auch in Assembler und nicht C sein.
Warum willst du ECX und EDX retten?
-
FrEEzE2046 schrieb:
Warum willst du ECX und EDX retten?
...ich glaube, dass man sie retten muss, weiss aber nicht genau...
-
abc.w schrieb:
FrEEzE2046 schrieb:
Warum willst du ECX und EDX retten?
...ich glaube, dass man sie retten muss, weiss aber nicht genau...
Also normalerweiße rettet man nur das EBX-Register. Welchen speziellen Grund meinst du denn?
-
FrEEzE2046 schrieb:
Also normalerweiße rettet man nur das EBX-Register. Welchen speziellen Grund meinst du denn?
Mit fällt kein spezieller Grund auf. Wenn's läuft, dann läuft's